|
| 1 | +# SPIKE C — the real per-application cost, measured on a never-completed application |
| 2 | + |
| 3 | +Unit `nts-t004/spike-c-thin-wrapper-cost`. Measured 2026-08-14 on one host |
| 4 | +(darwin-arm64, Node v24.15.0, npm 12.0.1). Machine record: |
| 5 | +`evidence/spikes/thin-wrapper-cost/verdict.json`. |
| 6 | + |
| 7 | +The spike was sent to price the post-industrialization per-application cost by |
| 8 | +taking a never-completed application through the frozen React adapter and |
| 9 | +witnessing it through the thin-wrapper path. It did not get there. What follows |
| 10 | +is what it did measure, and where it stopped. |
| 11 | + |
| 12 | +## Gate zero — license text at the pin |
| 13 | + |
| 14 | +Both candidates pass, read out of the consented archive already on disk after |
| 15 | +that archive was re-verified against the digest its ingest recorded. |
| 16 | + |
| 17 | +| application | pinned commit | license file | sha256 | gate | |
| 18 | +|---|---|---|---|---| |
| 19 | +| react-shlink-web-client | `44aca4ae` | `LICENSE` (MIT License) | `249a81967c48177d9fa4672adbfdecd356aba715101780e05d54fcbd744d699c` | pass | |
| 20 | +| react-sqlpad-v5-5-0 | `5c259dd7` | `LICENSE.md` (#The MIT License) | `93dec0b7b1f9775cdcb15603a6c1d8829164ac72fa01a4679845c85ee76421da` | pass | |
| 21 | + |
| 22 | +The primary passed, so no license fallback was taken. `react-sqlpad-v5-5-0` was |
| 23 | +read only as a comparator. |
| 24 | + |
| 25 | +## Where it stopped |
| 26 | + |
| 27 | +Two walls, both before the stage the ~3u estimate describes. |
| 28 | + |
| 29 | +**The frozen React adapter refuses the application.** `analyze` reads it as React |
| 30 | +with builder `unknown`; `plan` and `migrate` both refuse: |
| 31 | + |
| 32 | +> React plan: this tree declares neither react-scripts nor a Vite configuration, so no frozen React adapter claims it. This flow refuses rather than guessing an origin toolchain. |
| 33 | +
|
| 34 | +shlink-web-client v2.3.0 is an ejected create-react-app: it carries its own |
| 35 | +webpack 4 configuration under `config/` and does not declare `react-scripts`. |
| 36 | +This is a named gap. No frozen subtree was edited. |
| 37 | + |
| 38 | +**The era cell refuses the baseline.** With one Node era cell installed on this |
| 39 | +host, webpack 4 fails first on hashing — |
| 40 | +`error:0308010C:digital envelope routines::unsupported` — which |
| 41 | +`NODE_OPTIONS=--openssl-legacy-provider` answers, and then the build stops for |
| 42 | +good on the native dependency: |
| 43 | + |
| 44 | +> ./src/common/react-tagsinput.scss — Error: Node Sass does not yet support your current environment: OS X Unsupported architecture (arm64) with Unsupported runtime (137) |
| 45 | +
|
| 46 | +The corpus source is immutable, so swapping node-sass for dart-sass is not |
| 47 | +available, and no second era cell is installed. |
| 48 | + |
| 49 | +## The ledger |
| 50 | + |
| 51 | +| stage | machine | operator | outcome | |
| 52 | +|---|---|---|---| |
| 53 | +| license pre-screen (both) | 3 s | ~10 min | pass | |
| 54 | +| ingest completion (both) | 2 s | ~2 min | source complete both; no dependency closure for the primary | |
| 55 | +| baseline install | 20 s over 2 attempts | ~3 min | installed after one refusal (`EALLOWREMOTE`) and one operator decision (`--allow-remote all`) | |
| 56 | +| baseline production build | 10 s over 2 attempts | ~4 min | not built | |
| 57 | +| migrate under the frozen adapter | 1.04 s | ~2 min | refused | |
| 58 | +| migrate, admitted comparator (sqlpad client) | 0.95 s | ~1 min | materialised: 1 file written, 167 copied | |
| 59 | +| witness, thin-wrapper path | 0 | 0 | not executed | |
| 60 | +| **total** | **37 s** | **~22 min** | **0 builds, 0 witness passes, 0 new TypeScript lines** | |
| 61 | + |
| 62 | +Machine seconds are wall clock around the awaited command and nothing else. |
| 63 | +Operator seconds are the acts between commands — reading a refusal, choosing a |
| 64 | +remedy — and are never folded into machine time. |
| 65 | + |
| 66 | +## What this says about ~3u per application |
| 67 | + |
| 68 | +`threeUnitsCredible: false`, and the reason matters more than the flag: the |
| 69 | +claim was not reached rather than refuted. An application drawn from the |
| 70 | +never-completed set spent its whole budget on the stages *before* the one the |
| 71 | +estimate covers. Any per-application average that quotes only the applications |
| 72 | +that made it through is quoting a filtered population. |
| 73 | + |
| 74 | +Four costs remain manual, and this run priced the first three: |
| 75 | + |
| 76 | +1. **Era-cell provisioning** — two failed builds, ~4 minutes, no remedy on this host. |
| 77 | +2. **Install policy** (remote tarballs, install scripts) — one failed install, ~3 minutes; both mechanisable as policy, both judgment today. |
| 78 | +3. **Adapter admission** for trees outside the react-scripts/Vite declaration — ~2 minutes, then the application leaves the pipeline. |
| 79 | +4. **The migrated tree is not yet installable from the CLI.** On the admitted comparator, `migrate --materialize` wrote one file (the entry document) and copied 167; the lane's `package.json` still declares `react-scripts ^3.4.1` and carries no Vite configuration. The Vite-era rewrite for the applications already completed lives in per-application fixture code (18 to 318 lines each). |
| 80 | + |
| 81 | +Witness journey authoring and calibration were not touched here, so T002's |
| 82 | +reading of that stage stands unrevised. |
| 83 | + |
| 84 | +## The thin-wrapper floor, as inventory |
| 85 | + |
| 86 | +The pattern this spike was sent to price is real on disk — `react-dejavu-run.ts` |
| 87 | +is 61 lines and `angular-fuxa-run.ts` 67, over the 7,453-line generic harness, |
| 88 | +against 235 to 436 lines for the earlier per-application wrappers. That is |
| 89 | +inventory of work already done. It is not evidence that a new application |
| 90 | +reaches that floor, because no new application here reached the stage where the |
| 91 | +wrapper is written. |
| 92 | + |
| 93 | +## Not established |
| 94 | + |
| 95 | +- No build ran to completion, so nothing here establishes that either application builds on any era cell. |
| 96 | +- No witness pass ran, so nothing here establishes browser behaviour, parity, locality, or a bounded witness outcome. |
| 97 | +- The thin-wrapper line counts are inventory of previously completed applications, not a measurement of a new one. |
| 98 | +- Operator timings are single-run wall clock on one host, not a distribution. |
| 99 | +- The refusals are readings of this host and this pin; a different architecture, era cell, or npm would refuse differently, and none was tested. |
| 100 | +- Nothing here revises the frozen adapters, the supported matrix, or any capability status; no coverage or matrix artifact was regenerated. |
0 commit comments