Repository navigation
Show Muse Code as unavailable on iPhone with a truthful schema-1 allowance reader - #525
Conversation
…der (#522) Meta documents no sign-in or usage service an iPhone app can use for Muse Code subscriptions, so Add Account explains the limit and Muse Code can't be added, refreshed, scored or hold an account slot. A native reader for `muse usage --json` schema 1 maps fixtures to distinct, truthful states for any future supported source. Contract and limits are in MUSE-CODE.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…like refreshes (#522) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
@codex review |
1 similar comment
|
@codex review |
HemSoft
left a comment
There was a problem hiding this comment.
Independent Claude audit-pr review of bd7fda5 (Codex review hung >1h after re-request)
Reviewed head bd7fda54e99e25e54d3cf66ab56413435d74e39d against base and merge-base f2ce58a (main tip, so the branch is up to date). I read the full diff, the issue #522 body and research comment, and the pinned hs-pi-dashboard contract at 588be88.
Findings
1. Medium: the new DEBUG fixture adds an uncovered production function with CRAP 56, which will fail the manual iOS tests function-risk gate before release
- Anchor:
CodexBarIOS/Services/UITestMuseCodeFixture.swift:60-80,private static func result(for:configuration:now:). - Complexity: the pinned SwiftLint 0.65.1 with
scripts/function-risk/complexity.ymlmeasures CC = 7 for this function (seven switch cases). I ran this locally. - Coverage: the file is compiled into the
CodexBarIOSapp Sources phase.scripts/function-risk/policy.jsondoes not exclude it; it excludes onlyUITestFixtures.swiftandAppStoreScreenshotFixtures.swift. Nothing inCodexBarIOSTestsreferencesUITestMuseCodeFixtureor themuse-code-statesscenario, so its executable-line coverage in the unit-test result bundle is 0. - Score: CRAP = 7² × (1 − 0)³ + 7 = 56, above 30.
measure.pywill reportNew production risk above 30for this function.baseline.jsonhas no iOShigh_riskceilings to absorb it. TheiOS testsjob in a release or on-demandci.ymldispatch will fail, and AGENTS.md requires that job to pass before a release. - Precedent: the other two non-excluded UI fixture files,
UITestOpenCodeRenewalProviderandUITestSubscriptionBillingProtocol, are both exercised fromCodexBarIOSTests. This new file is the only one that isn't. - Evidence basis: inspection plus the measured complexity. I did not run the full coverage suite.
- Fix, either:
- add a unit test that calls
UITestMuseCodeFixture.seedandresults(in:scenario:"muse-code-states")on an isolated store and asserts each state's outcome; this also locks the screenshot evidence to real behavior; or - add a reviewed
excluded_filesentry with a rationale. That would need a FUNCTION-RISK.md note, per its change policy.
- add a unit test that calls
- Verify:
run-pro-release-validation.sh nativefollowed bymeasure.py --platform iosreports no errors.
No other actionable findings survived verification.
Verified (no finding)
- Gating holds. No production path can create, refresh or publish a Muse Code account:
allowAccountInsertionblocks bothaddAccountand new-accountupdate/save paths before the Pro check, so no paywall appears;canRefresh,refresh(),permitsRefreshandpermitsInsertionall checkisAvailableOnIPhone, so a Muse record never holds the free slot;- a deep link only scrolls to existing cards;
- every
ProviderID.allCasesconsumer is filtered, apart from keychain cleanup, which is harmless.
- Compatibility. Widget and watch targets don't compile
ProviderID. Existing raw values are unchanged and tested, and old persisted configurations still decode. - Contract match. The parser follows the pinned contract:
- field names, 0–100 used direction, cap at 100 with the raw forecast kept;
- reset after both
asOfMsand now, and within the window duration; - 60 s future tolerance, and the tier and source allowlist regexes;
- undocumented windows are named or counted, never shown as bars;
reasonandhintare never read;JSONValuekeeps"5"andtruefrom becoming numbers.
- Fixtures.
measured,partial,malformed-valuesandextra-windowmatch the producer fixtures byte for byte. - SUS. SUS is suppressed at every badge site, in the tile accessibility text and in the fleet entry.
- Freshness. A stale reading gets
barsFetchedAt = asOf, sohasCurrentBarsis false, there's no projection, and no alert or history is written (tested). - Changelog and docs. The user-facing line is under Added and the parser is under Developer Experience. README and MUSE-CODE.md match the code.
- Delivery.
- SwiftLint, the only required ruleset check, passes on a
pull_requestrun for bd7fda5. - Automatic CI is unchanged: no workflow edits.
- The Validation section has inline current-head screenshots, and the reason for omitting a recording is stated.
- SwiftLint, the only required ruleset check, passes on a
Notes (non-blocking)
- Owner acceptance needed. Issue AC 1 and 2 ask to "preserve" unknown billing, scope and unit fields. The PR deliberately drops them; for example,
billing.modeinextra-windowis ignored. The PR body states this, but the issue owner should accept the deviation. - Message wording. A window whose reset has passed is reported as "Muse Code sent an invalid value". The producer contract does the same, and the code is unreachable in production today, but a future source may want a distinct message.
- Merge controls.
- Codex review for bd7fda5 is still
running. - Live account checks remain pending for the account owner.
- The manual release gates (iOS tests with function risk, watch tests, full UI validation) have not run on this head.
- Codex review for bd7fda5 is still
…s within limits (#522) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Addressed the audit finding (Medium, function risk) in
The two notes are unchanged by design:
|
|
@codex review |
|
Codex Review: Didn't find any major issues. Swish! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Summary
Closes #522.
There's no supported way to read a Muse Code subscription allowance on iPhone. Meta restricts the subscription credential to the Muse Code CLI ("This credential is for use with Muse Code only"). It documents no OAuth, device-code or client registration for apps, and no network usage endpoint.
muse usageand MSPusage/readare CLI and local-host only. Sources and the two missing items are in the issue research comment and MUSE-CODE.md. No auth path is invented, no CLI client is reused, nothing is scraped, and token activity is never quota.What ships:
User-visible: Add Account says "Muse Code isn't available on iPhone" with the reason. Nothing else changes for users.
Muse Code can't become an account.
ProviderID.museCodeexists, but one predicate (isAvailableOnIPhone) blocks it everywhere:addAccountandupdate, on Free and Pro, with no paywall;canRefreshandrefresh();permitsRefreshandpermitsInsertion, so it never takes the free account slot.It isn't a widget focus choice and has no demo or App Store screenshot sample.
Schema-1 reader:
MuseCodeAllowancefollows the shipped producer contract (hs-pi-dashboard#71, codexbar#274), so a future supported source has a tested path.allowance:nullis unavailable, not 0.reason/hintare never read.Distinct unavailable states: not on iPhone, allowance not reported, unsupported format, unreadable, measurement missing or in the future, no valid windows. Sign-in expired, entitlement, PAYG, rate limit, timeout and transport are constructed states, because their wire shape is unknown. None of them shows zero or healthy.
Freshness: a reading measured more than 7 minutes earlier keeps its bars as last known (
barsFetchedAt= measurement time). It raises no new alerts, writes no history and gets no forecast.No SUS: no per-tile badge (including on unavailable tiles), no fleet entry and no price.
UI fixture: the DEBUG simulator scenario
muse-code-statesrenders synthetic states through the real dashboard for the evidence below. The shipping app can't reach these cards.Acceptance criteria
allowance. Null is distinct from a numeric 0.reason/hintnever surface (a synthetic email and API-key fixture proves it). Unsupported or missing schema versions fail safely. Billing, tier, scope, unit and per-model fields aren't reported by schema 1; documented as not reported rather than preserved.preserveCachedBarsOnFailure).tokensOnlyandextraWindowfixtures). No SUS, projection or alert without a current, valid window.Validation
Head
6c4f7f7on basef2ce58a(main).6c4f7f7only adds a fixture-coverage unit test after the independent audit; the app source and screenshots are unchanged frombd7fda5. Run on Air with Xcode, iPhone 17 simulator (iOS latest).swift package plugin … swiftlint lint): 0 violations in 287 files.MuseCodeAllowanceTests,AppAndWidgetTests,DashboardAndSettingsTests,AccountPlanAccessTests,UsageAlertTests) ata37725a: 285/285 passed.CodexBarIOSTestsatbd7fda5: 1,182/1,182 passed, 0 skipped.CodexBarIOSSmokeTests: passed.6c4f7f7:MuseCodeAllowanceTestswith coverage passed. Every function inUITestMuseCodeFixture.swiftandMuseCodeAllowance.swiftis at 100% except one trivial getter at 75%, so the release function-risk gate stays under 30. The full pinnedmeasure.pyrun is left to the release gate.MuseCodeAllowanceTests.CodexBarIOSTests, which only runs on manual dispatch.Screenshots
iPhone 17 simulator, light theme, default text size. The source is identical to
bd7fda5plus a local throwaway UI driver that only taps and scrolls (not committed). All Muse cards are syntheticmuse-code-statesfixtures that the shipping app can't reach. The green header dot on failed and stale cards is the existing shared card behaviour for every provider. Recording omitted: the only shipping change is static footer text with no interaction.Shipping change. Add Account explains that Muse Code isn't available on iPhone:
Fixture: allowance null (fixed text, no reason/hint, no SUS on the unavailable weekly tile), then exhausted (5-hour capped at 100%, red):
Fixture: exhausted weekly forecast, then measured 15% / 5% with plan pill and resets:
Fixture: not on iPhone (the acquisition-limit state):
Fixture: partial (5-hour invalid and named, weekly kept), then sign-in expired asking to update credentials:
Fixture: stale. Bars greyed as last known, no forecast, measurement age stated:
Council
Council: none consulted · missing: GPT 6.1 Sol (Codex weekly
pause, 188% projected,usage.py20:00 ET), Muse Wonder Full 1.0 (muse-codeWeeklypause, 245% projected) · Council unavailable.A fresh, independent Claude Opus 5.5 design critique ran as a P0 safeguard; it isn't a seat. Adopted 9 points:
Declined 1: an out-of-order observation guard. No acquisition path exists to produce one; it's recorded as a requirement for a future source in MUSE-CODE.md.
🤖 Generated with Claude Code