AppStore2031

archive

Withdrawn v1 resolution contract

A public AppStore2031 research record. The readable view is generated without changing the preserved source.

Open the exact Markdown source

Research boundary: Observed evidence, inference, scenario and fictional forecast claims retain the labels used in the source record.

Forecast contract — withdrawn method v1 record

Withdrawn and superseded. This file documents the first continuity-led method only. It is retained so readers can audit what failed and why, but it is not the active AppStore2031 method and must not be used to generate, validate, rank or publish the replacement forecast. The active method is documented in FORECAST_METHOD_V2.md.

Historical status at withdrawal: unfrozen research draft; never published.

This document defined the claims proposed for method v1, how those claims would have been produced, and how they would have been resolved. No edition was published under this contract. The text below is preserved in its historical form so its assumptions can be inspected.

Credibility commitment

AppStore2031 does not claim to know which fictional brands will exist. It makes dated, source-linked, probabilistic claims about app archetypes, categories, and rankings—and publishes in advance how those claims can be proved wrong.

The method draws on the OECD Strategic Foresight Toolkit, the UK Government's Futures Toolkit, Metaculus resolution guidance, Metaculus proper-scoring guidance, and Apple's current category definitions.

These are external standards, not evidence that any individual forecast is correct. In particular, scenarios are plausible futures used to challenge a forecast; they are not predictions in their own right.

1. Frozen forecast question

Once closed, the first edition answers:

As assessed at the edition manifest's exact asOf timestamp, what categories and app archetypes will occupy the Top Free iPhone charts during July 2031 across the defined regional storefront basket?

The edition manifest must freeze these fields before app generation:

forecastId: asf-2031-v1
methodVersion: 1
forecastHorizon: 2031
asOf: null while researching; exact ISO-8601 UTC time assigned by seal preparation
resolutionWindow:
  start: 2031-07-01
  end: 2031-07-31
chartFamily: top-free-iphone-apps
platform: apple-iphone-app-store
marketModel: coverage-balanced-global-composite-v1
probabilityFloor: 0.01
probabilityCeiling: 0.99
forecastCloseForScoring: 2031-06-30T23:59:59Z
rankModel:
  id: joint-rank-v3
  drawsPerStorefront: 20000
  minimumDrawsPerStorefront: 10000

Both the edition's evidence cutoff (treated as ending at 23:59:59 UTC) and its seal-assigned exact asOf timestamp must be no later than forecastCloseForScoring. Validation and seal preparation fail closed after that instant, preventing an edition from incorporating July 2031 resolution outcomes and then presenting itself as a pre-outcome forecast.

The target date shown to readers is 31 July 2031. Resolution uses the full calendar month so that a one-day promotion or news event cannot determine the result.

2. What is forecast and what is fictional

The fictional app name, developer, icon, screenshots, rating, reviews, and store description are educational scenario storytelling. They must be marked as fictional wherever they appear; a footer-only disclaimer is insufficient.

The resolvable unit is an app archetype: a bounded combination of user job, required capabilities, delivery modality, business model, likely provider type, and adoption mechanism. Fictional brand names are never scored.

Each archetype must:

  • Define three to seven observable required capabilities.
  • Define distinguishing capabilities and explicit disqualifiers.
  • Be distinguishable from every other archetype in its category.
  • Be applicable by a reviewer who cannot see its rank or rationale.
  • Be narrowed if more than three materially different current apps already satisfy its full definition.
  • Differ from neighbouring predictions by more than fictional branding.

One realised app may match at most one forecast archetype in a category, and one archetype may receive at most one realised match. Resolution uses the blind mapping process in BACKTEST.md.

3. Geographic contract

Apple does not publish a single global chart. The primary ranking is therefore a coverage-balanced global composite. It measures cross-market reach, not worldwide downloads, revenue, population, or installed-base share.

The proposed lens basket is frozen only after every underlying storefront has passed a chart-data availability check:

LensProposed storefronts
United Statesus
Mainland Chinacn
European Unionde, fr, it, es, nl, pl, se
Japanjp
South Koreakr
Indiain
United Kingdomgb
Southeast Asiasg, id, my, th, vn, ph
Taiwantw
Gulf technology economiesae, sa
Latin Americabr, mx
Africaza, ng, ke

Each lens has equal weight in the global composite. Storefronts inside a multi-country lens also have equal weight. A storefront may be removed or replaced only before the first edition freezes, for a documented data- availability reason. The final basket, weights, failed availability checks, and decisions are public.

Forecasts are authored and resolved at the storefront level. A multi-country lens is a reporting and weighting group, not another binary or ordinal outcome. Its coverage, joint Top-10 probability, expected points, and proper score are equal-weight means across its valid storefronts; its conditional rank distribution uses the existence-weighted formula in section 5. Those mixtures describe a uniformly sampled storefront within the lens; they are not scored as if the lens had one realised rank. The global composite first averages storefront values inside each lens and then averages the twelve lens values, preventing a seven-storefront EU lens from receiving seven times the weight of Japan.

A separate market-size-weighted view may be added later only if a credible, dated source for iPhone installed base is available. It is a secondary view and may not replace or rewrite the coverage-balanced result.

Global research coverage

Every material cross-global driver must show evidence coverage from:

  • The United States.
  • Mainland China.
  • The European Union.
  • At least one of Japan or South Korea.
  • At least one of India or Southeast Asia.
  • Any additional region materially affected by the claim.

Regional claims should prefer local primary sources. Original language and translation method must be recorded. A government plan is evidence of intent, regulation, or investment, never evidence that its promised outcome occurred.

4. Category contract

For a storefront, a category exists when Apple, or a successor first-party iPhone storefront explicitly named in the edition's fallback rules, presents it as a top-level browse category with an independently ranked Top Free chart during at least 16 days of the July 2031 resolution window.

Every current Apple category must be assigned a fate. Every proposed category must have a distinct discovery purpose and ten non-duplicate archetypes. A theme that cannot support ten archetypes is a collection or trend, not a category.

type CategoryFate =
  | "retained"
  | "renamed"
  | "merged"
  | "split"
  | "retired";

interface CategoryForecast {
  id: string;
  name: string;
  status: "current" | "proposed-new";
  definition: string;
  inclusionCriteria: string[];
  exclusionCriteria: string[];
  currentAppleCategoryIds: string[];
  fate?: CategoryFate;
  successorCategoryIds: string[];
  existenceProbabilityByStorefront: Record<StorefrontId, number>;
  existenceCalibrationByStorefront: Record<StorefrontId, {
    lensId: LensId;
    probability: number;
    nearestLowerAnchor: number;
    nearestUpperAnchor: number;
    sourceIds: string[];
    rationale: string;
    upwardCondition: string;
    downwardCondition: string;
  }>;
  lensCoverageSummaries: Record<LensId, number>;
  globalCoverageScore: number;
  driverIds: string[];
  claimIds: string[];
  strongestCountercase: string;
  signalIds: string[];
}

Each lensCoverageSummaries value is the equal-storefront mean inside that lens. The globalCoverageScore is the equal-lens mean of those summaries: an expected coverage index, not the probability that a majority of lenses will contain the category, and it is not scored as a binary probability. Categories at or above 0.50 appear in the primary forecast storefront and contain exactly ten ranked apps. Lower-coverage candidates remain visible in the category watchlist. Current categories below the threshold remain visible in the retired/merged account. The number of categories is an output of the research and is never fixed in advance.

Category-existence probabilities are scored separately for each storefront, then scores are macro-averaged within lenses and across lenses. The site may report realised coverage as a descriptive global outcome, but it does not publish or score a global-majority probability unless a later method version adds a frozen joint cross-storefront model.

5. App and rank schema

type RankBand =
  | "rank-1"
  | "rank-2-3"
  | "rank-4-5"
  | "rank-6-10"
  | "outside-top-10";

interface RegionalRankForecast {
  categoryExistsProbability: number;
  conditionalRankPmf: Record<RankBand, number>;
  jointTop10Probability: number;
  expectedTop10Points: number;
  jointModelRef: string;
}

interface LensRankSummary {
  categoryCoverageScore: number;
  conditionalRankPmf: Record<RankBand, number>;
  jointTop10CoverageScore: number;
  expectedTop10Points: number;
  storefrontIds: StorefrontId[];
}

interface AppForecast {
  id: string;
  editionId: string;
  categoryId: string;

  fiction: {
    name: string;
    subtitle: string;
    description: string;
    developerName: string;
    iconAsset: string;
    rating: number;
    imaginedReviews: Array<{
      title: string;
      body: string;
      stars: number;
      fictionalDisclosure: true;
    }>;
    fictionalDisclosure: true;
  };

  archetype: {
    name: string;
    userJob: string;
    requiredCapabilities: string[];
    distinguishingCapabilities: string[];
    disqualifiers: string[];
    deliveryModality: string;
    businessModel: string;
    likelyProviderType: string;
    adoptionMechanism: string;
    incumbentContinuity:
      | "existing-incumbent-evolves"
      | "new-entrant"
      | "platform-native"
      | "unknown";
  };

  forecast: {
    byStorefront: Record<StorefrontId, RegionalRankForecast>;
    lensSummaries: Record<LensId, LensRankSummary>;
    globalExpectedTop10Points: number;
    globalTop10CoverageScore: number;
    displayedGlobalRank: number;
    typicalStorefrontRankBand: RankBand[];
  };

  reasoning: {
    referenceClass: string;
    baseRate?: number;
    positiveUpdates: EvidenceUpdate[];
    negativeUpdates: EvidenceUpdate[];
    causalChain: string[];
    dependencies: string[];
    strongestCountercase: string;
    whyAboveNext: string;
    whyBelowPrevious: string;
    scenarioTests: ScenarioTest[];
    signalIds: string[];
    entrepreneurOpening: string;
  };

  claimIds: string[];
}

The conditional rank probability mass function must sum to 1. Probabilities are stored at full precision, displayed as whole percentages, and constrained to the edition's 0.01–0.99 bounds. To prevent zero cells while preserving joint rank capacity, published marginals mix 80% of the seeded simulation frequency with 20% of a fixed capacity prior. For the 20 candidates, that prior is each rank band's capacity divided by 20: {0.05, 0.10, 0.10, 0.25, 0.50}. Thus every conditional cell is at least 0.01 and every band still sums across candidates to its exact capacity {1, 2, 2, 5, 10}. Raw exact-rank and band counts remain published.

Joint coherence within a category

An app's rank PMF may not be elicited or edited independently. For each category and storefront, all candidate archetypes are ranked together in a single reproducible joint model. Each simulation draw assigns at most one candidate to each exact rank from 1 through 10. The published band PMFs are marginals aggregated from those exact-rank draws.

The joint model includes the ten displayed archetypes and enough explicitly labelled other-field candidates to represent incumbent, unforeseen, or unmodelled apps. Those placeholders are not additional forecast listings and cannot be scored as successful archetype predictions. They prevent the model from assuming that the project's ten selections must occupy all ten realised positions.

Every joint-model artifact records:

  • the category and storefront;
  • the complete candidate IDs, including other-field placeholders;
  • model version and input-data hash;
  • a deterministic random seed and at least 10,000 draws;
  • the exact-rank marginal matrix for ranks 1 through 10 plus outside the Top 10; and
  • a hash of the generated result.

For every draw, ranks are mutually exclusive. Across the resulting marginals, the sum of probability assigned to any exact rank is exactly 1, including other-field candidates. Consequently, the summed marginal capacity is exactly 1 for rank 1, 2 for ranks 2–3, 2 for ranks 4–5, and 5 for ranks 6–10. Because all twenty candidates are sorted, outside-top-10 has capacity 10. The site's ten published app PMFs are projections from this joint artifact and therefore may sum to less than those ranked capacities, but never more.

Manual narrative adjustments are inputs to a new joint-model run; they may not overwrite a single app's marginal after simulation. Category-existence probability is common to every candidate in the category/storefront and is applied only after the conditional joint ranking has been generated.

Numerical input and algorithm annex

data/SCHEMA.md and scripts/build-forecast-model.mjs are normative, versioned parts of method joint-rank-v3; a frozen edition records their SHA-256 hashes. The complete authoring JSON, numerical inputs, generated joint artifacts and result hashes are public. The current algorithm is:

storefrontFit = clamp(lensFit + storefrontAdjustment, 0.01, 0.99)
combinedStrength = 0.60 × baseStrength + 0.40 × storefrontFit
location = logit(0.02 + 0.96 × combinedStrength)
spread = 0.15 + 1.25 × uncertainty
utility = location + spread × seededNormalDraw

For each category/storefront, every draw ranks the ten forecast archetypes together with ten published other-field candidates whose base strengths are 0.92, 0.84, 0.76, 0.68, 0.60, 0.52, 0.44, 0.36, 0.28, 0.20, uncertainty is 0.65, and lens fit equals base strength. Default runs use 20,000 draws and may never use fewer than 10,000. The random seed is the first little-endian 32-bit integer of SHA-256 over joint-rank-v3|editionId|categoryId|storefrontId; the generator is Mulberry32 and normal draws use the Box–Muller transform. Stable candidate ID breaks an exact utility tie. The script and artifact expose position totals so this can be independently reproduced rather than trusted as a prose claim.

The authored app inputs are explicit forecast judgements, not observed measurements. They use these anchors:

Input0.20.50.8
baseStrengthNeed is plausible but adoption/reference class is weakRepeated adjacent use exists, but distribution or habit is unsettledDelivered recurring behaviour, strong need and a credible mass distribution route
lensFitMaterial local access, policy, infrastructure or affordability barriersMixed or neutral local conditionsLocal infrastructure, need and distribution reinforce adoption
storefrontAdjustmentDown to -0.15: strong local mismatch relative to peers in the lens0: no defensible local movement from the coarse priorUp to +0.15: strong delivered local advantage relative to peers in the lens
uncertaintyDelivered system with several independent observed sourcesImportant dependencies or scenario sensitivity remainPolicy targets, pilots or weak signals dominate

Intermediate values interpolate between the anchors. Every app publishes its reference class, positive and negative evidence IDs, dependencies, regional fit values, a base-strength rationale, an uncertainty rationale, twelve separate lens-fit rationales, and strongest counter-case beside the inputs. For every storefront in a multi-country lens it also publishes a local evidence record, a zero-sum ten-app adjustment vector, and an app-specific reason for each non-gap value. Each rationale compares the app's actual need, reference class, distribution, evidence, dependencies or local conditions with the nearest anchors. Inputs must never be generated from file order, app ID, current/displayed rank, a fixed decrement, keyword matching or a category-wide constant. Every category existence probability uses the same calibrated verbal ladder: 0.1 remote, 0.3 unlikely, 0.5 balanced, 0.7 more likely than not, and 0.9 highly likely because a durable discovery surface or delivered successor is evident. Values between anchors require a short comparison with the nearest two anchors in the public category research.

Every one of the 621 category/storefront probabilities has an existenceCalibrationByStorefront record. Validation requires the probability to match the scored input, the lens and storefront to match the frozen basket, the exact nearest anchors to match the value, every evidence ID to resolve and appear in the rationale, and upward and downward movement conditions to be present. If a blind packet has no local evidence for a cell, the source list must remain empty and the rationale must expose that gap rather than borrowing another storefront's evidence. A fresh calibrator authors each storefront judgement from a sealed packet that excludes all previous category probabilities, global scores, inventory ranks and joint-model output. The 621 rationales must be unique and must compare the evidence with both nearest anchors. Only after authoring is complete are probabilities integrated and the simulation rerun. The complete reader-facing table is rendered from those authored records in research/category-calibrations.md; it is not the source of them.

Category existence is estimated separately for all 27 storefronts, including Brazil and Mexico and each of South Africa, Nigeria and Kenya. An app begins with one of twelve broad lensFit priors. For the 20 storefronts inside the five multi-country lenses, a fresh author then judges an explicit storefront adjustment for every one of the ten apps before seeing generated ranks. Each storefront's vector is bounded to -0.15+0.15 on a 0.025 grid and sums to zero, so it changes relative conditional ordering without silently inflating the whole lens. The model consumes the clamped sum as storefrontFit.

There are 460 category/storefront adjustment records and 6,210 numeric cells: 1,620 independently reasoned multi-country app adjustments, 2,980 forced-zero gap cells, plus 1,610 single-storefront zero adjustments implicit in their already country-specific lens priors. Where the sealed local packet contains no evidence, all ten adjustments must remain zero, sources must remain empty and the gap must be stated. Only a source whose registered geography names the exact storefront country qualifies as local evidence; regional, global and neighbouring-country sources remain context and may not justify nonzero app adjustments. The complete public record is rendered in research/app-storefront-adjustments.md.

Lens-fit evidence is a three-level chain: each app publishes its direct reference class and counterevidence; its category publishes driver IDs used for regional infrastructure, policy, need and access; and each multi-country storefront adjustment cites the local category-calibration evidence from its rank-blind packet and names why the app's capabilities or delivery route move. A separately authored country may legitimately retain the same value as a peer when the evidence supports no finer distinction; the method does not mechanically perturb equal values merely to create geographic variation. A category may name D01–D16 directly or a calibrated category-driver registry entry; every registry entry in turn names one or more D01–D16 structural drivers. Validation requires every link to resolve. Because Brazil and Mexico are equal storefronts inside the Latin America lens, every D01–D16 driver must include at least one registered Brazilian and one Mexican record; evidence from one country, or from another region, cannot silently stand in for the other. The same rule applies separately to South Africa, Nigeria and Kenya. The local records remain inputs to judgement, not a formula that mechanically creates lensFit, storefrontAdjustment or category- existence probability.

This rubric does not pretend analyst judgement is mechanically deduced from sources. It makes that judgement inspectable and freezes it before simulation. A refresh records the old input, new input, numeric delta, evidence IDs and a short attribution to one or more anchors; it then reruns the whole joint model. Two analysts may disagree on an input, but neither can silently change a PMF, seed, field competitor or aggregation rule after seeing the result.

Rank-band points are:

Rank bandPoints
110
2–38.5
4–56.5
6–103
Outside Top 100

For storefront s:

jointTop10Probability
  = P(category exists in r)
    × P(rank is 1–10 | category exists in r)

expectedTop10Points
  = P(category exists in r)
    × Σ P(rank band b | category exists in r) × points(b)

For a lens with storefronts s, its categoryCoverageScore, jointTop10CoverageScore, and expectedTop10Points are the arithmetic means of those storefront values. Its conditional rank PMF is not a simple mean: it weights every storefront PMF by that storefront's category-existence probability and normalises by the sum of existence probabilities:

lensConditionalPmf(b)
  = Σ_s P(category exists in s) × P(b | category exists in s)
    / Σ_s P(category exists in s)

This guarantees that lens coverage multiplied by the lens conditional Top-10 mass equals the mean storefront joint Top-10 probability. The summary remains a mixture for a uniformly sampled storefront, not a single lens event.

globalExpectedTop10Points and globalTop10CoverageScore are equal-lens means of those within-lens means. The latter is expected storefront coverage under this two-stage sampling design. It is not a probability of a nonexistent global Apple-chart event and is not scored as one. Storefront joint Top-10 probabilities are scored separately, then macro-averaged by lens.

The ten apps are sorted by global expected Top 10 points; this mechanically sets the displayed rank. A precise rank therefore remains a visible commitment. The contract does not claim a probability distribution or confidence interval around that synthetic composite rank, because it has no joint cross-storefront dependence model.

Instead, typicalStorefrontRankBand answers a different, labelled question: conditional on the category existing in a storefront selected by the two-stage equal-lens/equal-storefront design, which smallest contiguous set of rank bands contains at least 80% of the conditional mass? Its global conditional PMF is computed by weighting each storefront PMF by that storefront's category-existence probability, first giving each storefront an equal share inside its lens and then each lens an equal share, before normalising. If several intervals use the same minimum number of adjacent bands, choose the one with greatest mass; if still tied, choose the interval containing the better ranks. The UI must call this a typical-market rank range, never an interval around the displayed consensus rank.

Every app explanation must state why it sits above the following app and below the preceding app. The first and tenth entries explain only the applicable side.

6. Evidence and public-process semantics

Every material claim points to a structured claim record, and every claim points to one or more source records.

interface Source {
  id: string;
  title: string;
  publisher: string;
  url: string;
  archiveUrl?: string;
  publicationDate?: string;
  accessedDate: string;
  cutoffCheck: {
    evidenceCutoff: string;
    accessedOn: string;
    publicationTiming: "dated-or-current-at-access" | "undated-at-access";
    latestKnownPublicationDate: string | null;
  };
  geography: string;
  originalLanguage: string;
  linkedLanguage: string;
  translationMethod: string;
  sourceType:
    | "official-policy"
    | "official-statistics"
    | "company-filing"
    | "research-paper"
    | "industry-data"
    | "expert-analysis"
    | "journalism";
  status: "used" | "contradictory" | "rejected" | "superseded";
  claimIds: string[];
  limitations: string[];
  metadataStatus: "complete" | "qualified";
  metadataCaveats: string[];
  rejectionReason?: string;
  snapshotHash?: string;
}

interface Claim {
  id: string;
  text: string;
  kind:
    | "observed-fact"
    | "reported-projection"
    | "policy-intent"
    | "inference"
    | "assumption";
  sourceIds: string[];
  geographicScope: string[];
  supportsEntityIds: string[];
  contradictsEntityIds: string[];
  analystNote: string;
}

interface ResearchEvent {
  id: string;
  occurredAt: string;
  actorType: "human" | "ai" | "tool";
  actorLabel: string;
  question: string;
  inputIds: string[];
  outputIds: string[];
  publicSummary: string;
  promptId?: string;
  modelId?: string;
  decisionId?: string;
}

The source-registry build extracts a machine-readable access date and the latest explicit full or month-level publication date from each record. It fails if either falls after the edition cutoff. Validation then compares the stored cutoffCheck with both the manifest cutoff and the calendar date of its exact asOf timestamp. Undated live pages remain explicitly labelled undated-at-access; a missing publication date is never silently converted into precision. The parser covers ISO and slash-separated numeric forms, day/month-name and month/day-name forms, abbreviated months, month/year and standalone future years. An ambiguous slash date is evaluated under both common day-first and month-first readings; if either valid reading crosses the cutoff, the later reading governs and the record fails closed.

claimIds is a generated reverse index, not an analyst's memory. It names the driver, category-claim and app entity IDs that cite the source in the edition's authored inputs. Refresh source deltas must reproduce this exact set alongside the source's normalized publication date, access date and geography. Edition validation independently rebuilds the reverse index from the edition-local driver, category/calibration and app files and rejects a fabricated snapshot entry before refresh deltas are considered.

Source metadata is fail-closed but not fabricated. Required public fields may contain an explicit qualified value such as “publisher not separately recorded” or “original language not recorded at source-record level”; in that case metadataStatus must be qualified, metadataCaveats must identify the inference or omission, and the record must carry a conservative limitation. Only a record whose fields came directly from its structured source block may be complete. The edition validator rejects null required fields, empty limitations and qualified records without caveats.

Publication rules:

  • Every material factual claim has an inline citation.
  • Every material source opened and reviewed is registered, including rejected, contradictory, and superseded sources.
  • The site publishes original analysis, structured extracts, research questions, relevant prompts, decisions, and links to originals.
  • It does not claim to publish private model chain-of-thought. Public summaries give evidence, assumptions, alternatives, decisions, and critic verdicts.
  • Copyrighted sources are summarised and linked, not reproduced wholesale.
  • “All research” means the complete reviewed research register, not every search-engine result that happened to be returned.
  • Source removal, forecast revision, and factual correction are separately dated events. None may silently rewrite history.

7. Forecast-production sequence

  1. Horizon scan: collect trends, emerging issues, weak signals, and plausible discontinuities.
  2. Driver map: classify political, economic, societal, technological, legislative, environmental, geopolitical, infrastructure, energy, capital, demographic, and platform-power drivers. Record impact, uncertainty, direction, geography, and evidence strength.
  3. Three Horizons: distinguish the established system, transition pressures, and emerging replacements.
  4. Critical uncertainties: identify high-impact, high-uncertainty drivers.
  5. Four scenarios: choose two sufficiently independent uncertainty axes and construct a 2×2 set. Do not assign scenario probabilities.
  6. Wind-tunnel: test every category and app causal chain against all four scenarios and relevant regional lenses. Read the full archetype, provider, delivery, causal chain, dependencies, regional variance and counter-case for each judgement. Never derive scenario viability or rank band from the app's current rank/index, keyword matching, regular expressions or a fixed template. The retained author-scenario-tests.mjs filename is a validator; it does not author or overwrite these qualitative records.
  7. Forecast synthesis: begin with a named reference class or base rate, record positive and negative evidence updates, and then state probabilities.
  8. Signals: define observations that would raise or lower each forecast.
  9. Ranking: calculate regional and global order from the frozen probability distributions. Do not hand-edit positions.
interface ScenarioTest {
  scenarioId: string;
  viability: "strong" | "survives" | "weak" | "fails";
  likelyRankBand: RankBand;
  rationale: string;
  brokenAssumption: string;
}

Scenario labels are explanatory, not ranking inputs: viable in all four is robust; three is resilient; one or two is scenario-dependent; failing in three or four is fragile.

8. Scoring contract

Each edition is scored independently against the same eventual outcome. Later editions must never be presented as if they were the original five-year forecast.

  • Binary category-existence and joint app-Top-10 claims use logarithmic loss and Brier score.
  • Ordinal rank-band probability distributions use multiclass logarithmic loss, with Ranked Probability Score as a distance-sensitive diagnostic.
  • Ranked Top 10 lists use Rank-Biased Overlap at depth 10 with persistence parameter p = 0.9.
  • Top 10 overlap, Kendall's tau-b on matched archetypes, mean absolute rank error, unforeseen entries, and category precision/recall are secondary diagnostics.
  • Calibration tables and reliability plots carry explicit sample-size warnings.

For binary outcome y ∈ {0,1} and probability p:

logLoss = -(y ln(p) + (1-y) ln(1-p))
brier = (p-y)^2

Lower is better for both. Probability bounds prevent infinite logarithmic loss. The full retrospective protocol and win condition against the naïve baseline are defined in BACKTEST.md.

9. Signal and update contract

interface Signal {
  id: string;
  statement: string;
  directionIfObserved: "raises" | "lowers" | "ambiguous";
  threshold: string;
  geography: string[];
  cadence: "monthly" | "quarterly" | "annual" | "event-driven";
  sourceIds: string[];
  nextCheckAt: string;
}

A refresh must:

  1. Keep asOf null while the edition is a mutable research draft; seal preparation assigns the exact close timestamp and locks the status.
  2. Search for evidence published after the previous cutoff while retaining the previous source register.
  3. Recheck every due signal.
  4. Record old probability, new probability, delta, evidence IDs, and reason.
  5. Recompute ranks mechanically.
  6. Publish additions, removals, movements, and unchanged forecasts.
  7. Create a new immutable edition rather than editing the old one.

Freeze and publication seal

researching editions are mutable working drafts, keep asOf: null, and must be labelled as such. Seal preparation atomically assigns the exact current asOf time and moves the manifest to closing before validation. Every authoring, packet, model and evidence-snapshot writer accepts only researching, so the forecast cannot change after its claimed close. A failed preparation restores researching and asOf: null; a successful one remains locked in closing. Sealing is deliberately two-stage so an external receipt can never be requested for a root that does not exist yet.

  1. prepare:seal validates the edition, computes a canonical sorted path/hash bundle over authored inputs, the edition-local sources.json and drivers.json snapshots, normative method/schema/ seal scripts, inventory and every joint-model artifact, then writes an exact seal proposal containing that root. The manifest is represented in the root by a canonical projection of every field except the lifecycle-only status, frozenAt, freezeRoot and publishedAt fields. This permanently binds the question, asOf, market, chart, probability, scoring and model parameters while still allowing finalisation to change lifecycle state. Shared root data/sources.json and data/drivers.json are working inputs for the next edition and are deliberately excluded: each edition manifest binds the hashes of its own copies, which the edition seal includes.
  2. The owner publishes that exact proposal with the complete sealed content at a raw.githubusercontent.com URL whose Git object path contains a full immutable 40–64 hexadecimal revision ID. Seal protocol v1 then requires an Internet Archive Wayback id_ snapshot of that exact immutable URL. The fourteen-digit archive timestamp is the independent receipt ID.
  3. freeze:edition accepts only that closing edition, recomputes the root, byte-compares the remote proposal, verifies that the immutable URL uses the supplied full revision, fetches the archived copy and byte-compares it too, and only then appends the root, files, response hashes and anchor identifiers to data/freeze-ledger.json and changes the manifest to frozen.
  4. Every later validation repeats both remote fetches and content checks in addition to recomputing all local hashes. Unavailable or changed external evidence is a validation failure, not an invitation to trust the ledger.

The builder refuses an edition when either its manifest is not researching or its ID already appears in the ledger, so merely flipping the manifest back cannot authorise a rebuild. Re-preparing after any content change requires deleting the unanchored proposal first; an anchored or ledgered edition can never be prepared again.

A local proposal or ledger is not an independent timestamp. Therefore an edition may not be labelled published until the immutable Git object and its byte-identical Wayback snapshot exist. Supporting another timestamp authority requires a new, reviewed seal-protocol version; an arbitrary receipt URL or self-declared authority is never accepted. The current build scope does not authorise either external action, so it remains a research draft. A refresh skill may only copy from a frozen, externally attested source edition.

A change is material when a category is added, merged, split, renamed, or retired; a probability changes by at least five percentage points; a displayed rank moves by at least two places; a typical-market range crosses the Top 10 boundary; a core dependency or counter-case changes; or new evidence overturns a material assumption.

10. July 2031 resolution contract

For every included storefront and category:

  • Capture the official Top Free iPhone chart at local noon every day from 1–31 July 2031.
  • Preserve the raw response, screenshot, retrieval time, URL, and hash.
  • Give daily rank k the value 11-k; give nonappearance zero.
  • Require at least 16 valid daily captures.
  • Average daily points and sort them to form the realised monthly Top 10.
  • Apply the locked archetype definitions through blind independent mapping.
  • Resolve a storefront category as existing only if it meets the 16-day category rule.

The canonical source is the signed-out, human-facing first-party iPhone category page that visibly identifies the storefront, category and Top Free chart. RSS or other structured feeds are diagnostics only; they never replace the canonical ranks merely because they differ. By 2031-06-30T23:59:59Z, before any outcome day, publish and hash a resolution source registry. For categories already live, it contains the exact canonical URL, category identifier, rendered-chart selector or extraction rule, locale, and one successful test capture for every storefront/category pair.

Proposed-new, renamed, merged or split categories cannot be required to have a URL before they launch. For those forecast categories, the June registry instead freezes: (a) the exact signed-out top-level category-directory URL and selector; (b) a daily local-noon procedure that records every category link, label, identifier and first-seen timestamp before opening any linked chart; (c) the forecast category's already-published inclusion and exclusion boundary; and (d) the following mapping rule, which is fixed by this contract now and may only be copied—not redesigned—in June 2031.

Before opening any discovered chart, three coders work independently. They may see only the directory link label and identifier plus the destination page's title, breadcrumb and category description. They may not see chart positions, app names, icons, ratings, reviews or another coder's answer. Each coder must assign the discovered link to exactly one published forecast-category ID or to no-match, using the already-frozen inclusion and exclusion rules. A link maps only when at least two of the three coders independently choose the same forecast-category ID. A split vote is no-match; it is not adjudicated after chart data become visible.

Assignments are one-to-one in both directions: one observed chart may resolve at most one forecast category, and one forecast category may use at most one observed chart. If two qualifying links receive the same forecast-category assignment, the link with the earlier directory first-seen timestamp wins. A same-timestamp tie is resolved by lexicographically ascending Apple category identifier, then by canonical URL. The other link remains preserved as discovery evidence but cannot contribute ranks or existence to another forecast category. The predecessor/successor arrays in categories.json document the taxonomy hypothesis only; they do not pre-assign a 2031 chart or override this rule.

A newly discovered link accepted under that rule becomes the category's canonical page from its first observed day. Its chart is captured that same day and on every remaining July day. A launch on 16 July can therefore still supply the 16 valid days needed to qualify; a launch after 16 July cannot satisfy the existence rule. Surprise categories are preserved as discovery evidence but cannot be retrofitted to a forecast category whose frozen boundary they do not meet. The 30 June registry must include the exact candidate-label sheet, coder instructions, assignment form and a digest of this unchanged rule before any July discovery record is collected.

Current-category fate resolution

The retained, renamed, merged, split and retired fields are testable categorical forecasts, not decorative lineage notes. They resolve separately for every storefront using current-category-fate-v1 in categories.json. The same three rank-blind coders receive each frozen 2026 predecessor name, identifier and boundary plus only a discovered 2031 link's label, identifier, title, breadcrumb and category description. They may not see ranks, apps, icons, ratings, reviews or one another's answers. Two of three votes establish whether an observed chart continues a predecessor purpose or, for a split, covers a material subdomain. This continuity coding is separate from the one-to-one forecast-category assignment above: an observed merged chart may continue several predecessors without being assigned to several forecast categories.

For a storefront, the fates resolve as follows:

  • Retained: the single listed successor qualifies; that same observed chart receives continuity votes for the predecessor; its normalized directory label equals the normalized 2026 currentName; and no second observed chart independently continues the predecessor.
  • Renamed: the single listed successor qualifies and receives predecessor continuity votes; its normalized directory label differs from the 2026 currentName; and no separate chart with the old normalized label independently continues the predecessor.
  • Merged: exactly one chart qualifies for the shared listed successor; every 2026 predecessor that names that successor receives continuity votes for that same chart; and none has a separate independent continuation. The whole inferred merge group must pass—a partial group is a failure.
  • Split: the predecessor has no independent continuation; every listed successor qualifies as a distinct observed chart; and every successor receives continuity votes that it covers a material subdomain of the frozen predecessor boundary. Requiring all listed successors is deliberate: two or a majority is insufficient.
  • Retired: the predecessor has no independent continuation and no qualifying listed successor.

Label normalization is Unicode NFKC, lower-case, trimmed, whitespace-collapsed text with punctuation removed. If an old-label or otherwise independent predecessor chart coexists with a renamed, merged or split successor, the transformed fate fails even when the successor exists. A fate is ambiguous only when technical unavailability of the frozen directory or qualifying page prevents a determination on more than fifteen July days; otherwise unmet conditions are failures. Report per-storefront outcomes, equal-storefront lens success shares and an equal-lens descriptive global share. These fates have no probability forecast in this edition and therefore do not enter the proper probability score.

If a registered canonical request fails at local noon, retry the same URL at +5, +15, and +30 minutes. If all attempts fail, that day is missing. Do not switch surfaces during July. A fallback may be used only when it was named and test- captured in the frozen June registry and the canonical surface was already documented as permanently withdrawn before the registry froze. A web/feed disagreement is preserved as provenance but resolved in favour of the frozen human-facing page. For a category already live by 30 June, failure to register a qualifying page makes the storefront/category unresolvable. For a proposed or transformed category, no page before launch is expected: resolvability comes from the frozen directory-discovery procedure and its daily captures. Fewer than 16 valid chart days after a qualifying first appearance means the category does not meet the 16-day existence rule; it is ambiguous only when technical unavailability of the frozen directory or qualifying chart prevents that determination. No surface or category mapping may be chosen after chart outcomes are inspected.

For a multi-storefront lens, report the share of valid storefronts in which the category exists, and the equal-storefront mixture of realised rank bands and points. Do not collapse those distinct outcomes to one invented lens rank. Global category coverage is reported descriptively as the equal-lens mean of those valid-storefront shares. It is not compared with a purported global existence probability; proper scoring applies to each storefront forecast and is macro-averaged first within lenses and then globally. If a category does not exist, its apps' joint Top 10 outcomes resolve No; conditional rank forecasts are not separately scored. If the first-party App Store ceases and no successor defined in the frozen edition satisfies the contract, the affected questions are annulled rather than retrospectively redefined.

The scorecard must show the original 2026 edition, every refresh, the naïve persistence baseline, ambiguous outcomes, and missing data separately.

11. Machine-checkable invariants

Validation must reject an edition when:

  • A primary-storefront category has other than ten ranked apps.
  • Displayed ranks are missing, duplicated, or disagree with computed order.
  • A rank probability mass function does not sum to 1 within numeric tolerance.
  • A regional/category rank artifact was not generated from one reproducible joint model, assigns two candidates to one exact rank in a draw, or its exact-rank and band-capacity sums fail the joint-coherence rules.
  • A published app PMF differs from the marginals in its referenced joint-model artifact.
  • A probability lies outside the frozen bounds.
  • A material claim has no source, or a source has no URL and limitations note.
  • A fictional element lacks its explicit disclosure flag.
  • A current category is absent from both the primary taxonomy and the retired/merged account.
  • A new category has fewer than ten distinct archetypes.
  • An app lacks a counter-case, regional forecasts, scenario tests, signals, or an adjacent-rank explanation.
  • A later edition mutates a previously published snapshot.