Skip to content

test(40): capture a launcher minted by today's mint as the pre-phase fixture - #43

Merged
hyperpolymath merged 3 commits into
mainfrom
feat/40-metadata-block-fixture
Sep 22, 2026
Merged

hyperpolymath merged 3 commits into
mainfrom
feat/40-metadata-block-fixture

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Closes the first acceptance criterion of #40, and nothing else.

  • A launcher minted by today's mint is committed as a fixture, in a commit that changes nothing else, before either phase begins.

Why this is its own PR, not the first commit of phase 1

#36 was squash-merged. A squash collapses a branch into one commit, so "a
commit that changes nothing else" would stop existing the moment phase 1
landed on top of it. The criterion is checked with git diff --name-only
against main, so the fixture has to reach main as its own commit —
which means its own PR.

The ordering is the whole point of the criterion. From #40:

Capture it after phase 2 and you are asserting the new emitter against the
new parser — which passes regardless of whether backwards compatibility
survived.

Provenance — reproducible from this repository alone

The fixture is the real output of the real binary at the base commit. It was
not hand-filled from the template.

base:       154b9b61c5162edab026119e54ce540bfffe7dff (origin/main)
build:      cargo build --release -p launch-scaffolder
invocation: ./target/release/launch-scaffolder mint \
              examples/stapeln.launcher.fixture.a2ml --stdout
result:     rc=0, 471 lines, block at lines 5-22

The input, examples/stapeln.launcher.fixture.a2ml, is already committed, so
there is no external input to lose.

What it captures

# @a2ml-metadata begin
# (
#   id                   = "stapeln-launcher"
#   type                 = "launcher"
#   version              = "0.1.0"
#   app-name             = "stapeln"
#   app-display          = "Stapeln"
#   app-url              = "http://localhost:4010"
#   runtime-kind         = "server-url"
#   standards-compliance = [
#     "launcher-standard.adoc"
#     "LM-LA-LIFECYCLE-STANDARD.adoc"
#     "cross-platform-system-integration-modes"
#   ]
#   standard-spec-version = "0.4.0"
#   generator             = "launch-scaffolder"
# )
# @a2ml-metadata end

Verification

  • git show --stat HEAD → 1 file changed, 471 insertions. No code, no
    template, no test.
  • Committed 100644 — the fixture is read by tests, never executed, so it is
    deliberately not marked executable.
  • Contains zero tab characters, which matters later: a tab is invalid
    anywhere in a deed, so the phase-1 bridge could not accept this block if it
    carried one.

Scope

No test asserts this fixture yet — that is criterion 2, and it belongs to
phase 1. Shipping the assertion here would mean the fixture and its test
arrive together, which is exactly the coupling criterion 1 exists to prevent.

Out of scope per #40: config.rs, discovery.rs, cmd_config.rs (tracked as
hyperpolymath/standards#960), and the dated audit records under
docs/ruleset-audit-2026-04-10/.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WPSJ7fBhVAMcpSffCBWUDo

Issue #40's first acceptance criterion, verbatim: "A launcher minted by
today's mint is committed as a fixture, in a commit that changes nothing
else, before either phase begins."

This commit is that criterion. It adds exactly one file and touches no
code, no template and no test, so the fixture provably predates both
phases. Capturing it after phase 2 would assert the new emitter against
the new parser, which passes whether or not backwards compatibility
survived.

Provenance — reproducible at the base commit:

  base:       154b9b6 (origin/main)
  build:      cargo build --release -p launch-scaffolder
  invocation: ./target/release/launch-scaffolder mint \
                examples/stapeln.launcher.fixture.a2ml --stdout
  result:     rc=0, 471 lines, @a2ml-metadata block at lines 5-22

The input config examples/stapeln.launcher.fixture.a2ml is already
committed, so nothing outside the repository is needed to reproduce it.

Committed 100644: the fixture is read by tests, never executed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WPSJ7fBhVAMcpSffCBWUDo
Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Advanced

Run ID: c2a23e37-5d41-47ee-a8b0-596ef0f45631

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 11aec464-a69e-431e-b019-c32c7cb1d5f4

📥 Commits

Reviewing files that changed from the base of the PR and between 154b9b6 and c9cc76a.

📒 Files selected for processing (1)
  • crates/launcher-common/tests/fixtures/metadata_block/minted-2026-09-22_stapeln-launcher.sh

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.

📜 Recent review details
⏰ Context from checks skipped due to timeout. (11)
  • GitHub Check: governance / Security policy checks
  • GitHub Check: governance / Guix primary / Nix fallback policy
  • GitHub Check: governance / Well-Known (RFC 9116 + RSR)
  • GitHub Check: governance / Language / package anti-pattern policy
  • GitHub Check: governance / Trusted-base reduction policy
  • GitHub Check: governance / Licence consistency
  • GitHub Check: governance / Check Workflow Staleness
  • GitHub Check: governance / Code quality + docs
  • GitHub Check: governance / Workflow security linter
  • GitHub Check: hypatia / Hypatia Neurosymbolic Analysis
  • GitHub Check: CodeQL Analysis (actions, none)
🧰 Additional context used
🪛 Shellcheck (0.11.0)
crates/launcher-common/tests/fixtures/metadata_block/minted-2026-09-22_stapeln-launcher.sh

[warning] 56-56: APP_PORT appears unused. Verify use (or export if used externally).

(SC2034)


[style] 94-94: See if you can use ${variable//search/replace} instead.

(SC2001)


[warning] 315-315: Declare and assign separately to avoid masking return values.

(SC2155)

🔇 Additional comments (1)
crates/launcher-common/tests/fixtures/metadata_block/minted-2026-09-22_stapeln-launcher.sh (1)

53-53: 🎯 Functional Correctness

No fixture-comparison defect is established.

render() embeds the canonicalised config path, so output can differ between checkouts. The launcher-common sources and tests contain no comparison between this fixture and freshly rendered output. The requested normalisation is not tied to an implemented comparison.


📝 Summary

Summary by CodeRabbit

  • New Features
    • Added a launcher for Stapeln with options to start, stop, and check the server, open its browser page, or view help.
    • The launcher can install or remove system shortcuts and app integration, and reports errors through available desktop notifications or dialogs.
    • Startup checks whether the server is reachable and provides a fallback timeout.

Walkthrough

This change adds a generated Bash launcher fixture for the Stapeln app. The script includes metadata, platform detection, server start and stop logic, browser opening, Linux desktop integration and removal, help output, and command-line mode dispatch.

Changes

Launcher fixture script

Layer / File(s) Summary
Script metadata and environment
crates/launcher-common/tests/fixtures/metadata_block/minted-2026-09-22_stapeln-launcher.sh
Adds the generated file header, embedded metadata block, runtime configuration, startup command selection, logging helpers, GUI error reporting, platform detection, and per-platform install target paths.
Server lifecycle and browser actions
crates/launcher-common/tests/fixtures/metadata_block/minted-2026-09-22_stapeln-launcher.sh
Adds PID-file based status checks, stale PID cleanup, URL polling, server startup with timeout handling, server stop logic, and platform-specific browser launch commands.
Desktop integration and removal
crates/launcher-common/tests/fixtures/metadata_block/minted-2026-09-22_stapeln-launcher.sh
Adds Linux desktop file generation, launcher and icon installation, desktop database refresh, optional delegation to launch-scaffolder provision, confirmation handling for existing installs, and installed target removal for --disinteg.
Help and mode dispatch
crates/launcher-common/tests/fixtures/metadata_block/minted-2026-09-22_stapeln-launcher.sh
Adds the usage output and the main mode switch for --start, --stop, --status, --browser, --auto, --integ, --disinteg, and help handling, plus unknown-mode failure behaviour.

Priority: ⬇️ Low

Estimated code review effort: 4 (Complex) | ~40 minutes

Change: Other

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant LauncherScript
  participant ServerProcess
  participant URLProbe
  participant Browser

  User->>LauncherScript: run --auto
  LauncherScript->>ServerProcess: start selected startup command
  LauncherScript->>URLProbe: poll URL with curl
  URLProbe-->>LauncherScript: reachable or timeout
  LauncherScript->>Browser: open configured URL
Loading

Merge Risk: ⚪ Minimal · up to c9cc7

This adds a raw launcher fixture without changing shipped runtime behavior. No current merge-blocking risk is established; it is ready to merge after normal checks.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 18 functions across 1 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title states 'capture a launcher minted by today's mint as the pre-phase fixture'. The raw summary confirms the PR adds a new launcher script file (stapeln-launcher.sh) that is the output of the…
Description check ✅ Passed The description directly addresses the changeset. It explains that the PR closes the first acceptance criterion of issue #40 by committing a pre-phase fixture. The description provides context for why…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

I minted a launcher with a careful hop,
It can start the server and make it stop.
I tidied the desktop with icons in line,
Then checked the URL says all is fine.
I nibbled on flags till the help was clear,
And thumped with delight: the fixture is here.

Comment @coderabbitai help to get the list of available commands.

APP_PORT="4010"
WAIT_SECONDS="15"

PID_FILE="/tmp/stapeln-server.pid"
WAIT_SECONDS="15"

PID_FILE="/tmp/stapeln-server.pid"
LOG_FILE="/tmp/stapeln-server.log"
@coderabbitai

coderabbitai Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

🤖 Completed: Fix pre-merge checks in PR #43 — View commit 1c2a605

hyperpolymath and others added 2 commits September 22, 2026 23:56
Phase 1 of #40: a compat reader that accepts the `@launcher-deed`
dialect
alongside the `@a2ml-metadata` block every launcher minted to date
carries.
**The emitter is untouched.** Phase 2 switches `mint`, gated on a tagged
release carrying this — per the owner's ruling that "baked" means a
tagged
release, not a merge to `main`.

Stacked on #43, which supplies the fixture. GitHub retargets this to
`main`
when #43 merges.

## ⚠ This repo has no Rust CI, so a green check here proves nothing

Measured: `.github/workflows/` holds six files — `codeql.yml`,
`governance.yml`,
`hypatia-scan.yml`, `labels.yml`, `label-triage.yml`,
`push-email-notify.yml` —
and `grep -rn 'cargo test\|cargo nextest'` over that directory returns
**zero**.
No workflow builds or tests the crates. Whatever goes green on this PR
is
governance and scanning, not Rust.

So the local run below is the only real evidence, and it is quoted
rather than
summarised. Filed as #45, with acceptance criteria, per the
standing rule that a new finding is an issue, not a merge blocker.

```
running 66 tests   (lib)
test result: ok. 66 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
running 5 tests    (tests/deed_corpus.rs)
test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
running 4 tests    (tests/round_trip.rs)
test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
```

`cargo clippy --all-targets -- -D warnings` is clean.

## A passing suite proves nothing until a mutant dies

#40 asks for exactly this. Eight mutants, each applied to a clean tree
and
reverted after:

| # | mutation | result |
|---|---|---|
| A | legacy (backwards-compat) arm returns `Ok(None)` | **8 tests
red**, incl. `the_committed_legacy_fixture_still_parses` |
| B | deed arm returns `Ok(None)` | **8 tests red**, incl.
`a_deed_dialect_block_parses` |
| C | `app-display` mapped to the deed's `:name` instead of `:display` |
`both_dialects_flatten_to_the_same_values` **red**;
`both_dialects_agree_on_what_todays_emitter_produces` **red** |
| D | `node.head != "praxis-deed"` check removed |
`a_deed_block_that_is_not_a_praxis_deed_is_rejected` **red** |
| E | `:standards` string-count strictness check removed | **survived at
first — see below** |
| F | `:beholding-chora` requirement removed |
`a_deed_block_without_beholding_chora_is_rejected` **red** |
| G | `rewrite_scalar`'s deed guard removed |
`rewrite_scalar_refuses_a_deed_block_rather_than_corrupting_it` **red**
|
| H | both-dialects rejection falls through to legacy |
`a_script_carrying_both_dialects_is_rejected` **red** |

**Mutant E survived the first pass, and that was a real gap.**
`Value::str_list()` skips non-strings *silently*, so a symbol or integer
smuggled into `:standards` would vanish from the compliance claim. The
reader
compares `str_list().len()` against `as_list().len()` for exactly that —
but
nothing tested it, so the comparison was dead code that would have
shipped
looking correct. Added
`a_non_string_entry_in_standards_is_reported_not_silently_dropped`;
mutant E
now dies. That test exists *because* the mutant survived, which is the
whole
argument for running them.

Worth recording: removing the both-dialects arm outright (mutant H's
first
form) does not compile — the match is exhaustiveness-checked. H was
re-run as
a semantic mutant instead, which is the honest test.

## Criterion 5 — the round trip, delivered not deferred

`mint → parse → realign → parse`, on both forms, in
`crates/launcher-common/tests/round_trip.rs`. No CLI needed: `realign`
has no
rewrite path in phase 1 — `cmd_realign.rs:156` calls `template::render`
and
`:172` writes the result — and `template::render` is public, so the test
drives
the identical call `realign_one` makes.

- `mint_parse_realign_parse_is_stable_for_the_legacy_form` — also
asserts the
  two renders are byte-identical, which is what `Outcome::Unchanged`
(`cmd_realign.rs:163`) is decided on. If that ever stops holding,
`realign`
  rewrites every launcher on every run.
- `both_dialects_agree_on_what_todays_emitter_produces` — the deed
sample is
**generated from the live emitter's own output**, not typed by hand, so
it
  moves when the emitter moves. This is the "on both forms" half.
- `realign_cannot_edit_a_deed_launcher_in_place`
- `phase_one_mint_emits_the_legacy_markers_and_not_the_deed_ones` —
states the
no-emitter-change claim as a test, so phase 2 has to delete it
deliberately.

The generator carries a guard that panics if `mint` ever emits a scalar
the
deed dialect has no slot for — silently dropping one is precisely the
phase-2
regression this change exists to prevent. Verified non-vacuous: removing
`generator` from that match list turns two tests red with the intended
message.

## Why the deed form is not re-scanned here

The `#` prefix is stripped and the text handed to `deed::parse`, the
normative
grammar. A second s-expression scanner in this file would be cheaper
today and
would manufacture a second DEED grammar that nothing forces to agree
with
`deed.rs` — it would keep passing while being wrong the moment the
normative
grammar moves. Delegating gets the tab check, escape handling, `#u5`
literals,
`#t`/`#f`, and list-vs-clause disambiguation for free.

`the_real_deed_grammar_is_the_one_enforcing_the_block` proves the
delegation is
real: a literal tab inside the block must produce the `HTAB` diagnostic,
a rule
only the real grammar knows. A hand-rolled scanner here would accept it.

## Scope

```
$ git diff --name-only origin/main
crates/launcher-common/src/metadata_block.rs
crates/launcher-common/tests/fixtures/metadata_block/minted-2026-09-22_stapeln-launcher.sh   (#43)
crates/launcher-common/tests/round_trip.rs
```

Zero `.tera` files. Zero diff in `cmd_config.rs`, `config.rs`,
`discovery.rs`
and `template.rs` — `config.rs`/`discovery.rs` are standards#960, not
this.

`is_deed()` is derived from the captured marker line rather than stored
as a
struct field, so there is no API break and it cannot desync from
`raw_lines`.

The new marker deliberately does not say `a2ml`: A2ML is retired, and a
marker
carrying the name would propagate it into every launcher minted from
here on.

## One unrelated observation

`cargo fmt --check` is red on `main` today, independent of this PR —
rustfmt
collapses a five-line `app_license` insert in `template.rs` to one.
Running
`cargo fmt --all` in any PR silently pulls that into the diff; reverted
here so
the "no emitter change" claim stays clean. Not fixed here — it is not
this PR's
to carry.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01WPSJ7fBhVAMcpSffCBWUDo

Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@hyperpolymath
hyperpolymath merged commit f323fdc into main Sep 22, 2026
16 checks passed
@hyperpolymath
hyperpolymath deleted the feat/40-metadata-block-fixture branch September 22, 2026 23:06
hyperpolymath added a commit that referenced this pull request Sep 23, 2026
Phase 2 of #40. Phase 1 shipped the compat reader; this converts the
emitter, so
`mint` now writes `@launcher-deed` instead of the retired
`@a2ml-metadata` form.

Closes the emitter half of #40. Follows #43 (the pre-phase fixture),
which this
change depends on and which made the strongest test here possible.

## It is a pure dialect change, and that is what makes the test strong

The compliance data is byte-identical in both dialects. So the central
test is
not "the new block parses" — it is that the new emitter's flattened
output is
**equal to the committed pre-phase fixture's**, field for field:

```rust
assert_eq!(legacy.scalars, minted.scalars);
assert_eq!(legacy.lists,   minted.lists);
```

A launcher minted today and one minted before the change carry the same
values.
That is the compat promise, asserted against an artefact rather than a
reconstruction.

## The escape filter is the exact inverse of its consumer, deliberately
no stricter

`deedstr` was written against `deed.rs`'s `lex_string`, not against
intuition:

| character | grammar | filter |
|---|---|---|
| `"` `\` `\n` `\t` | the only four legal escapes | escaped |
| other `< U+0020` | rejected by the lexer | **reported as an error** |
| **U+007F (DEL)** | **accepted** — the check is `< 0x20` | **passed
through** |

A filter rejecting U+007F would be stricter than the parser it feeds —
the
estate's most-recurring trap, a guard asking a different question than
its
consumer. CR is the opposite case: it has *no* legal spelling in a deed
string
at all, so it is an error rather than a silent drop. Refusing to mint
beats
minting a launcher whose own metadata cannot be read back.

⚠ The tab case reaches furthest. `deed::parse` rejects a literal HTAB
**anywhere
in the document**, tested on the raw text before lexing — so a tab
surviving into
a value would not corrupt one field, it would make the whole block
unparseable.
The emitted template is verified to contain zero literal tabs.

Registered as a Tera filter rather than pre-escaping the context, so the
escape
applies at exactly the emission sites and every other interpolation in
the script
keeps its raw value. (Tera autoescaping is HTML-shaped and does not fire
for
`.sh` in any case — without this, a display name holding one `"` closes
the
string early.)

## `:standards` — measured, not assumed

An earlier review flagged that the emitted block claims compliance with
`launcher-standard.adoc` while D73-C converted that standard to `.deed`,
so a
fresh mint might fail AC4's currency gate. Measured instead:

- `docs/UX-standards/launcher-standard.adoc` **exists** on `standards`
`main`
(it was the `.a2ml` that was deleted), as does
`LM-LA-LIFECYCLE-STANDARD.adoc`.
- `scripts/check-launcher-standard-currency.sh:34-37` states verbatim
that
`launcher-standard.adoc` is *"a DIFFERENT document (the human-readable
UX
  standard) and is deliberately NOT checked here."*
- The gate's canonical file is `launcher-standard_praxis.deed` at
`0.4.0`.

So the block is correct as emitted and the gate exempts it by design. No
change
needed, and no owner ruling required.

⚠ `:schema-version` is the **grammar** version (`1.0.0`);
`:standard-version` is
the **document** version, read live from the real deed via
`standard.rs:100-108`
— not hardcoded, and not interchangeable with the former.

## `config set` now refuses on freshly-minted launchers — by design, and
owner-ruled

`cmd_set` calls `rewrite_scalar`, which declines to edit a DEED form in
place.
Phase 2 therefore changes observable CLI behaviour: `config set`
hard-fails on
every launcher minted from here on.

**Put to the owner and ruled: leave it refusing.** A deed block is a
generated
artefact; in-place scalar surgery on it is how you get a launcher whose
metadata
no longer parses. The config file stays the single source of truth and
re-mint is
the only edit path. Zero new code — the refusal is already covered by a
test.

`cmd_config.rs`'s user-facing strings are corrected to match: the "no
`@a2ml-metadata` block found" message named only the retired dialect
while the
reader has accepted both since phase 1.

## Four mutants killed

A passing suite proves nothing until a mutant dies.

| mutant | result |
|---|---|
| **A** `deed_escape` made the identity function | 4 tests red |
| **B** emitter drops one compliance standard | 1 test red — the paired
control alone, proving it checks the **data**, not merely that two
things parsed |
| **C** emitter reverts to the legacy markers | 4 tests red |
| **D** emitter changes the `:generator` value | 2 tests red |
| clean restore | 72/72 — so every red above is attributable to the
mutant, not ambient state |

⭐ **Mutant D found something worth reporting.**
`both_dialects_agree_on_what_todays_emitter_produces`
stayed **green** under it, because it generates its legacy leg *from*
the deed the
emitter just produced — so under a uniform value change both legs move
together
and the equality still holds. It proves the transform, never the value.
That is
not a defect (it exists to prove cross-dialect agreement, and it does),
but it
means the committed fixtures are the only thing anchoring the emitter to
a
known-good value set. Hence the second commit.

## Two committed fixtures, one facing each way

- `minted-2026-09-22_stapeln-launcher.sh` (legacy, from #43) — proves a
launcher
  minted **before** the change still reads. **Not edited by this PR.**
- `minted-2026-09-23_stapeln-launcher-deed.sh` (new) — proves a launcher
minted
**during** it still reads after some later tightening of the DEED
grammar.
`deed::parse` is shared with the estate and will keep moving; launchers
already
  written will not.

Both captured from the real emitter, neither hand-typed, neither derived
from the
other.

## ⚠ The two red phase-1 guards were inverted deliberately

`round_trip.rs` carried
`phase_one_mint_emits_the_legacy_markers_and_not_the_deed_ones`,
whose own doc comment reads *"Stated as a test rather than left to the
diff, so
phase 2 has to delete this line deliberately."* It did its job. Both it
and
`mint_parse_realign_parse_is_stable_for_the_legacy_form` now assert the
phase-2
contract, pointing the other way, so a revert has to delete them just as
deliberately.

Two **further** tests in that file had gone green-but-degenerate rather
than red —
subtler, and easy to miss. Since `mint()` now returns a deed, their
variable named
`legacy` held a *deed* block, so "both dialects agree" was comparing
deed against
deed. The legs are inverted.

## Verification

```
cargo test --workspace   ->  72 + 5 + 6 = 83 passed, 0 failed
cargo clippy --workspace --all-targets  ->  rc=0, zero warnings
rustfmt --check on all touched files    ->  0 diffs
```

⚠ **`launch-scaffolder` has no Rust CI** (#45) — six workflows, not one
runs
cargo, so 18 `.rs` files and 59+ `#[test]` fns have never executed in
CI. The
local output above is the evidence for this PR, and that is a statement
of what
is *not* proven here, not a claim of coverage.

Incidental: this also cures one pre-existing `rustfmt` drift in
`template.rs`
(the `app_license` chain) that was already red on `main`, in a file this
PR is
editing anyway.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01WPSJ7fBhVAMcpSffCBWUDo

---------

Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
arena-ai-coding-agent Bot pushed a commit that referenced this pull request Sep 25, 2026
#40's criteria are all implemented in code shipped by PRs #43, #44 and #46.
What the issue still asks for is the write-up: the measurements, taken on
a named commit, with the numbers attached.

Recorded here:

* the fixture predates both phases, and still carries artefacts no
  post-phase emitter can produce;
* PR #44 touched only metadata_block.rs and round_trip.rs — the template
  is absent from its file list, which is the "phase 1 shipped alone"
  claim, checked rather than remembered;
* the phase-1 fixture test after phase 2, including the one assertion
  that had to change and why that is not a compatibility break: every
  value assertion is untouched and still passes, and the restored
  phase-1/2-era assertion fails naming exactly the four fields #41
  started enforcing;
* the eight round-trip tests and what each pins;
* the mutant kill — reverting the legacy arm of parse_from_text to
  `return Ok(None)` fails 11 tests, reverting that restores 98 passing.

Two things are recorded as still open rather than quietly omitted: #45
AC4 (actions.lock could not be generated here) and the `--version` gap
between the generated launcher and the standard's (required-modes).

Closes #40

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants