Files
lanework/RELEASE.md
T
rzen ade7d34cd8 Land the 2026-07-31 design-ruling sweep
Uncommitted ruling prose from the pro-m1 sessions, committed as found:
trash sorts newest-first by modified stamp (no rank minting); kind-blind
trash selection; native undo in every tier with the provider following
the board; session-coarsening for card-window stacks; column-major
masonry; changed-path channel (02); window-scoped comment-thread heals;
commit-message vocabulary growth; integrity commit author; signature
passed per-commit instead of repo config; repo-state validation
tightening; comments pane defaults on; draft close-failure guard;
deferred comment-trash purge; 2.0 ships only with pro-m1 (RELEASE.md).

Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
2026-07-31 17:49:18 -04:00

8.6 KiB
Raw Blame History

Distribution and release

The channel decision (recorded 2026-07-29)

Lanework ships on the Mac App Store, as version 2.0 of the existing dev.rzen.indie.Kanban App Store record — the 1.x app already listed there under the name Lanework. This was not an open question by the time this document was written; three prior rulings settle it:

  • The one-app collapse (DESIGN/12-editions.md, re-ruled 2026-07-30, superseding the 2026-07-27 two-app split) puts the whole family on one record: dev.rzen.indie.Kanban, the id 1.x already ships under, so 2.0 is simply its update. Lanework Pro arrives inside it as a subscription after pro-m1/pro-m2, never as a second record.
  • The marketing version has been 2.0 since m3 — the successor numbering of the shipped 1.x.
  • The portfolio's whole release tooling (appstore-publish skill, asc-*.swift scripts, the account's API key) is App-Store-shaped, and the 1.x pipeline for this very record already exists and works.

Notarized direct distribution is deliberately not pursued for 2.0: a second channel means a second update path and a second set of listing assets for no current audience, and nothing in the app requires escaping the App Store's sandbox rules (the app is already sandboxed with user-selected file access, and its network-client entitlement stays dormant until Pro's remotes use it). Revisit only if App Review rejects something architectural.

The pipeline

Carried over from the 1.x release (same record, same scheme names — the pathfinder repo's pipeline, now living here):

  • scripts/release.sh — XcodeGen regenerate, xcodebuild archive (Release, generic/platform=macOS), -exportArchive with scripts/ExportOptions-macOS.plist (destination=upload — straight to App Store Connect). Build number = git commit count, stamped by the existing post-build phase.
  • .env.release (gitignored; .env.release.example committed) — account-level App Store Connect API credentials.
  • scripts/metadata/ — the listing source of truth (name, subtitle, description, keywords, what's-new, URLs, categories, pricing, availability, review notes). Pushed with the canonical scripts, always with --platform macos:
set -a; source .env.release; set +a; swift ../indie-skills/skills/appstore-publish/scripts/asc-metadata.swift --bundle dev.rzen.indie.Kanban --version 2.0 --platform macos --dry-run
  • Screenshots: scripts/metadata/screenshots/en-US/APP_DESKTOP/ — needs fresh 2.0 captures (see checklist).

First-release (2.0) checklist

Run top to bottom; nothing below "PUSH POINT" may run without a deliberate decision — every step after it writes to the live App Store record of a shipping 1.x app.

  1. All milestone work committed and pushed (build number = commit count).
  2. Unit suite green: xcodebuild test -project Kanban.xcodeproj -scheme Kanban -destination 'platform=macOS,arch=arm64' -only-testing:KanbanTests.
  3. UI test pass on a real display (KanbanUITests: accessibility audits + end-to-end golden flows), plus the manual checklists (KanbanUITests/AccessibilityVerification.md, toolbar/undo/trash/drag-preview lists).
  4. CHANGELOG.md current (it is the in-app release notes) — What's New (scripts/metadata/version/en-US/whats_new.txt) tells the same story.
  5. Screenshots: capture the 2.0 board on a real display (APP_DESKTOP sizes come straight from screenshots of the running app; numeric filename prefixes set the store order).
  6. Archive dry run: scripts/release.sh at least through the archive step completes locally.
  7. — PUSH POINT (everything below touches the live record) —
  8. scripts/release.sh — archive + upload the build.
  9. Metadata dry run, then push (asc-metadata.swift --platform macos, commands above).
  10. Verify pricing (currently free, carried from 1.x) and availability (ALL territories) still match intent — Pro will be the paid tier later.
  11. Stage: asc-submit.swift --bundle dev.rzen.indie.Kanban --version 2.0 --platform macos (waits for build processing, attaches, stages the review submission — does not submit).
  12. Review the staged listing at appstoreconnect.apple.com (age rating, privacy labels, and content rights carry over from 1.x — the stage step's errors will name anything missing).
  13. Submit: the same command with --submit.

Lanework Pro (the subscription)

Pro is a subscription inside this app, not a second record (DESIGN/12-editions.md ▸ Distribution, re-ruled 2026-07-30): the two-app split that once wanted its own bundle id, metadata folder and scheme here is retired. Nothing in the pipeline above changes for it — same scheme, same archive, same upload. The added work is App Store Connect configuration and review materials, and it is all below.

The app side is built (the entitlement, the tier seam, the Settings Pro section, the local Configuration.storekit). The store side is not and must not be until pro-m1 ships something to sell: a live subscription product against a build whose Pro tier binds the same native undo stack the free tier does would be selling nothing. So every step here is future work for the pro-m1 release, not for 2.0.

2.0 does not ship before pro-m1 is ready — the tiers launch together (user-ruled 2026-07-31). This closes the would-be window where a shipped Settings Pro section faces a nonexistent product and shows "App Store can't be reached" — a false sentence (store reachable, product not configured). With the window ruled out of existence, that state only ever shows when something is genuinely wrong, and its shared wording for product-not-found vs network-down stays accepted as-is. The push-point items below remain user-gated; this rule adds the ordering constraint above them.

What exists in the repo today

  • Kanban/Tier/ProProducts.swift — the identifiers, mirrored from App Store Connect: product dev.rzen.indie.kanban.pro.monthly, group reference name Lanework Pro. The group's numeric id is read off the loaded product at runtime, never hardcoded.
  • Configuration.storekit (repo root) — the same group and product as an Xcode-local StoreKit configuration, attached to the Kanban scheme's run action (project.ymlschemes.Kanban.run.storeKitConfiguration). It makes the subscribe/manage/restore flow exercisable with no ASC product and no sandbox account. buildPhase: none — it never ships.
  • Entitlements: no in-app-purchase key is needed. In-app purchase is an App Store Connect fact about the record, not a sandbox capability; the app calls StoreKit with the entitlements it already has.

Checklist — pro-m1 release (not 2.0)

Steps 14 are App Store Connect work done by hand at appstoreconnect.apple.com; there is no script for them and no API step in this repo's tooling. They are all below the PUSH POINT in spirit — each one touches the live record of a shipping app.

  1. Create the subscription group on dev.rzen.indie.Kanban: reference name Lanework Pro. One group — a second would let a user hold two Pro subscriptions at once.
  2. Create the auto-renewable subscription in it: product id dev.rzen.indie.kanban.pro.monthly, reference name "Lanework Pro Monthly", duration 1 month. The product id must match ProProducts.monthly exactly and can never be changed or reused once created.
  3. Set the price (choose the tier; all territories, matching the app's ALL-territories availability) and the localized display name and description. The app never spells a price — it renders product.displayPrice, so the store is the only source.
  4. Subscription review materials, which are separate from the app's: a review screenshot of the Settings Pro section showing the price, Subscribe and Restore Purchases; review notes naming Settings (⌘,) as the path to the purchase surface, that the subscription unlocks git-backed history and sync, and that there is no account or login of any kind.
  5. Confirm the app's own listing carries the required subscription furniture: a link to the privacy policy and to the terms of use (EULA), both reachable from the listing, plus the auto-renewing terms in the description. Apple rejects auto-renewable subscriptions without them.
  6. Update Configuration.storekit's displayPrice to whatever step 3 set, so a development run and the store agree.
  7. Verify in a sandbox account before submitting: subscribe, confirm the Settings section flips to "Subscribed — renews …", confirm the reopen offer appears with boards open, then Manage Subscription and Restore Purchases.
  8. Then run the ordinary release checklist above for the pro-m1 version. The subscription is attached to that version's review submission.