skip to content
Replays

Gantry's Gated Demo Edition

A try-before-you-buy build that checks in, refuses offline when exhausted, and unlocks to unlimited.

Gantry milestones

3 milestones 10 sprints 32 agents

5 plan 11 execute 14 review 7 fix

219k peak context

93k median execute

A gated demo that unlocks runtime access and verifies release artifacts.

3h 2m total 12m 38s per sprint

5m 44s plan 1h 7m execute 25m 58s review

71 edits 813 commands

codex harness

Gantry's ordinary distribution path was a paid binary. This job built a separate demo edition that could prove who was using it, ask the server before a build starts, stop when access is unavailable or exhausted, and later unlock into an offline unlimited state.

The run split that work by boundary: first the compile-time and identity foundation, then the runtime gate and unlock path, then release artifacts and end-to-end checks. Some early stamp-reader work has since been replaced by a runtime email identity flow, but the demo feature, gate policy, HTTP client, token cache, unlock command, lifecycle hooks, and release producer support are still present in the tree.

How this walkthrough is structured

Feature

What did the run build and ship?

The tree now has a demo-only licensing surface behind a cargo feature, with server check-in, completion reporting, local unlock state, command dispatch, and release packaging still visible at HEAD.

Build

How did Gantry structure the work?

The cut kept the paid build boundary in front, isolated policy from lifecycle integration, and left the run's hardest stress in the gate core and the later wiring that made that policy visible.

Milestone 1

Demo Identity Setup

3 sprints 11 agents 1h 7m wall time 111k peak context

The lasting part of this milestone is the cargo feature boundary and the documented unlock-key placeholder. The original personalization-stamp module and its top-level tests no longer exist at HEAD, and the current demo gate gets identity from email-derived state instead of scanning a stamped executable. That means the milestone's runtime reader cannot be described as an isolated surviving module, but its dependency boundary still frames every later demo module.

This milestone was scoped to the boundary a fresh agent could prove before any server behavior existed. It had to keep the paid edition clean while giving the demo edition a place for identity code and later token verification. The first two child sprints both hit red gates and were repaired, which put the stress at the compile-time and binary-shape edges rather than in policy logic. The final reader sprint stayed within the foundation boundary and finished without the same repair pattern.

Feature Boundary

3 agents 21m 35s wall time 111k peak context 1 fix

Cargo still exposes a separate `demo` feature that enables the demo-only HTTP, hashing, and token-verification dependencies. The default feature set remains aimed at development tooling and screencast support, not demo licensing. The placeholder key documentation also survives under `config/demo-unlock.md`, while the placeholder public key file itself has since changed enough that the original inserted line is not identifiable.

This was the smallest viable slice of the demo edition: add the off-by-default feature and prove that the ordinary build did not gain network or signature-verifier machinery. A fresh agent could hold it because it had no runtime policy to decide and no lifecycle hook to place. Its gate went red after review and was repaired at the dependency boundary. That made the paid-build cleanliness check the useful boundary for the rest of the run.

Stamp Slot

3 agents 22m 25s wall time 87k peak context 1 fix

The dedicated `personalization_stamp` source file from this sprint is gone, along with the old slot tests. Current demo behavior no longer depends on a binary stamp reader in the main tree. What remains visible from the job around this area is indirect: later demo code operates from cached or supplied identity rather than from this original slot module.

This sprint carried an edition-neutral binary concern: reserve one passive personalization surface without turning it into licensing behavior. It was still compact enough for a memoryless worker because the brief asked only for embedding and proof of uniqueness, not parsing or enforcement. Its gate failed once and repaired, which fits a task whose risk was in optimized binary output rather than application control flow. The sprint boundary kept that risk away from the demo feature itself.

Stamp Reader

2 agents 15m 1s wall time 79k peak context

The reader's standalone implementation is no longer present at HEAD. The current gate uses `DemoGateIdentity` with an email hash, backed by environment input, an interactive prompt, and a small identity cache. The sprint's feature claim therefore survives only as the broader requirement that demo policy consumes a typed identity and treats missing or invalid identity as a refusal state.

The reader completed the identity foundation by giving later work a typed answer instead of raw executable scanning. Its brief made clear what it must not do: no server call, no unlimited fallback, and no paid-edition behavior. Unlike the two earlier identity slices, it did not need a repair pass after the gate. That made it a contained parser task at the end of the foundation milestone.

Milestone 2

Gate Unlock Runtime

5 sprints 20 agents 1h 29m wall time 219k peak context

This milestone is the part most visible in the current tree. `src/demo_license.rs`, `src/demo_http.rs`, and `src/demo_gate.rs` still hold the cache verifier, transport client, and gate decisions, while `src/main.rs`, `src/commands.rs`, and the build engine carry the dispatch and lifecycle integration. The integration tests now live under the current `tests/integration/default` layout and still cover checked builds, refused starts, unlock, cached unlimited state, and management commands that must not phone home.

This milestone was the main runtime build: token trust, transport, policy, lifecycle entry points, and the user-facing unlock command. The decomposition kept transport and decision logic separate before the gate touched real builds, which gave each worker a narrower surface to test. The decision core triggered the run's re-plan, and the lifecycle wiring then needed extra execution and review attention. That is where the architecture had to adjust after the policy shape became concrete.

Unlimited Token Cache

2 agents 9m 28s wall time 99k peak context

`src/demo_license.rs` still loads `license.json`, verifies the cached token against the embedded demo unlock key, and treats missing or invalid cache data as ordinary demo state. The module exposes `CachedLicense` and `UnlimitedLicense` for the gate layer rather than deciding command behavior itself. Its tests still exercise token shape, signature failure, payload mismatch, expiration, and cache loading paths.

This sprint was the offline trust base for everything that followed. It had a clear input and output: read a cache file, verify the signed payload, and report whether the demo should be treated as unlimited. Because it did not need command dispatch or network calls, the worker could focus on malformed cache files, tampering, expiration, and default demo state. The run facts show no repair pass here, so the boundary held cleanly.

Demo HTTP Client

3 agents 11m 47s wall time 93k peak context 1 fix

`src/demo_http.rs` still provides the demo-only blocking JSON client. It posts to `/demo/check`, `/demo/used`, and `/demo/unlock`, normalizes success, exhausted, invalid-code, malformed-body, status, and transport outcomes, and respects `GANTRY_DEMO_API`. The dependency remains behind the `demo` feature, so ordinary builds do not link the HTTP client.

The transport sprint was asked to speak the server contract without owning policy. That made the unit small enough for a fresh worker: normalize responses for check, used, and unlock calls, honor the base URL, and leave the meaning of those outcomes to later code. Its gate went red and was repaired, locating the difficulty in response classification and failure preservation. The later policy code could then depend on typed outcomes instead of HTTP details.

Gate Decision Core

4 agents 12m 33s wall time 97k peak context 1 fix 1 replan

`src/demo_gate.rs` still contains the central decision types and functions. Startup accepts a cached unlimited license without network work, otherwise derives or loads demo identity, asks the server, and returns allowed or refused states with specific stderr text. Completion reporting is also policy-level: unlimited mode is a no-op, demo mode reports the build token and completion credential, and reporting failure becomes a warning.

This was the policy sprint, intentionally before lifecycle wiring. It combined identity, cached unlimited state, and HTTP outcomes into startup and completion decisions that could be tested with injected parts. The gate went red and repaired, then review forced a re-plan of the remaining milestone work. That boundary event is important: once the pure decision surface existed, the run adjusted the following integration work around the actual allowed result it produced.

Build Lifecycle Wiring

5 agents 37m 50s wall time 219k peak context 1 fix

The build engine still carries an optional demo gate through its context and reports completion from the finalization path. `src/main.rs` performs demo startup gating for build-like commands and leaves help, version, diagnostics, configuration, listing, and other management flows outside the gate. Current integration tests assert that exhausted or identity-missing demo starts stop before agent work, successful runs report completion, and already-complete resumes do not count again.

This sprint moved from pure decisions into real build ownership, which made it the broadest runtime integration cut. It had to run the gate before agent work, carry the allowed result until completion, and leave management or already-complete paths alone. The record shows a red gate, a fix, a review note, and another execute pass before it settled. The brief's corrected boundary was that completion reports from the identity inside the allowed gate result, not from a separately preserved stamp.

Unlock Verb

3 agents 12m 42s wall time 107k peak context 1 fix

`gantry unlock` is still registered only when the demo feature is compiled. The command loads Gantry config, calls the demo HTTP client, verifies the returned unlimited token through the gate and license modules, writes the cache, and exits nonzero for invalid code, offline transport, bad token, or cache failure. Default-build tests still assert that the paid command surface does not expose the unlock verb.

The unlock sprint was a command-level capstone on top of the token cache and HTTP client. Its job was narrow: parse the demo-only verb, redeem a code, verify the returned token before trusting it, and write the cache only on success. The gate went red and was repaired, putting the remaining stress at the user-facing command boundary. Because the verifier already existed, the worker did not have to reopen the token format while adding dispatch.

Milestone 3

Demo Release Verification

2 sprints 8 agents 16m 34s wall time 84k peak context

The release script still builds paid and demo Linux tarballs from the stripped source tree, signs a combined checksum manifest, and self-verifies the assembled output. The demo lifecycle coverage also still exists, now in the integration test suite, and checks the real command path against a local server. The old top-level test files named in the git facts have been reorganized rather than left in place.

The final milestone moved from runtime behavior to distribution and proof. Its first sprint changed the local release producer, while the second exercised the composed path against a local server. Only the producer sprint needed a repair after a red gate; the end-to-end hardening sprint stayed green. That split kept packaging contract risk separate from the runtime flow it was verifying.

Demo Release Artifacts

3 agents 7m 29s wall time 71k peak context 1 fix

`scripts/release/build-local-release.sh` still has separate paid and demo package arms. The demo arm builds from the stripped tree with default internal tooling disabled and the demo feature enabled, then writes demo tarballs beside the paid ones. The checksum block still lists the paid tarballs, demo tarballs, source-review archive, SBOM, and notices while keeping verification files out of the manifest.

This sprint was a producer-side handoff rather than another runtime change. It asked one worker to extend the existing local release builder additively: paid artifacts keep their path, demo artifacts are built with the demo feature, and the manifest includes only shipped assets. Its gate failed once and repaired, locating the risk in catalog and manifest exactness. The runtime gate was already present, so this unit could focus on packaging shape.

Demo Release Hardening

2 agents 4m 28s wall time 84k peak context

The integration tests still exercise the demo path through a copied Gantry binary and a local server. They cover verified email caching, counted completion, exhausted refusal before agent work, identity-missing starts, unlock redemption, cached unlimited builds that skip the server, and management commands that do not contact the gate. The tests have moved under the current integration layout, so the original top-level files named by the job facts no longer isolate this sprint by path.

The last sprint was a composition check over work that was already built. Its brief asked for the local-server flow, refusal cases, unlock behavior, and paid-edition boundary to be asserted together. It did not need a fix pass, which suggests the earlier separation left enough stable surface for end-to-end coverage to bind. As a closing unit, it was about proving the pieces still interacted through the intended contracts.