Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"schema_version": 1,
"workflow_version": 2,
"workflow_origin_version": 2,
"id": "accept-windows-refused-connection-wording-in-the-isolation-test",
"slug": "accept-windows-refused-connection-wording-in-the-isolation-test",
"title": "Accept Windows' refused-connection wording in the isolation test",
"description": "Accept Windows' refused-connection wording in the isolation test",
"kind": "bug_fix",
"state": "accepted",
"canonical_applied": true,
"base_commit": "c65af7f55d832475c877fb9032bc89da4bb685f3",
"created_at": 1790441579,
"updated_at": 1790448323,
"affected_specs": [],
"affected_paths": [
"tests/isolation.rs"
],
"no_spec_change": true,
"no_spec_change_rationale": "Only tests/isolation.rs changes, and tests/ is outside source_dirs (src, templates). The behavior under test is unchanged: the default TempEnv GitHub base is loopback and the spawned search fails with a refused connection. The test now also recognizes the Windows wording of that refusal, which ureq 3.4 passes through from the OS. specs/github/testing.md already describes the test in wording-neutral terms.",
"acceptance_criteria": [
"default_temp_env_points_github_at_a_dead_port in tests/isolation.rs passes on Linux, macOS and Windows: it still asserts the default TempEnv GitHub base starts with http://127.0.0.1: and that the spawned templates search fails, and it recognizes the refusal as 'connection refused' (Linux, macOS) or Windows' WSAECONNREFUSED wording ('actively refused' / 'os error 10061'), so a genuine api.github.com failure still does not satisfy it; cargo test --locked is green on ubuntu-latest, macos-latest and windows-latest with both the ureq 3.3.0 lockfile on main and the ureq 3.4.2 lockfile the v1.8.0 release carries"
],
"selected_artifacts": [
"context",
"testing",
"tasks"
],
"dependencies": [],
"answers": {
"architecture_risk": "no",
"public_contract": "no"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"approvals": [
{
"gate": "definition",
"actor": "user:0xLeif",
"timestamp": 1790447727,
"digest": "4d3c64c5dd4d951b2b09fbd0e6463bc55c0d33f14a4eb7aca98775cfcf6d3694",
"note": "Approved by Leif in the orc session, 2026-09-26: fledge #537",
"approved_scope": {
"schema_version": 1,
"change_id": "accept-windows-refused-connection-wording-in-the-isolation-test",
"title": "Accept Windows' refused-connection wording in the isolation test",
"description": "Accept Windows' refused-connection wording in the isolation test",
"kind": "bug_fix",
"affected_specs": [],
"affected_paths": [
"tests/isolation.rs"
],
"no_spec_change": true,
"no_spec_change_rationale": "Only tests/isolation.rs changes, and tests/ is outside source_dirs (src, templates). The behavior under test is unchanged: the default TempEnv GitHub base is loopback and the spawned search fails with a refused connection. The test now also recognizes the Windows wording of that refusal, which ureq 3.4 passes through from the OS. specs/github/testing.md already describes the test in wording-neutral terms.",
"acceptance_criteria": [
"default_temp_env_points_github_at_a_dead_port in tests/isolation.rs passes on Linux, macOS and Windows: it still asserts the default TempEnv GitHub base starts with http://127.0.0.1: and that the spawned templates search fails, and it recognizes the refusal as 'connection refused' (Linux, macOS) or Windows' WSAECONNREFUSED wording ('actively refused' / 'os error 10061'), so a genuine api.github.com failure still does not satisfy it; cargo test --locked is green on ubuntu-latest, macos-latest and windows-latest with both the ureq 3.3.0 lockfile on main and the ureq 3.4.2 lockfile the v1.8.0 release carries"
],
"dependencies": [],
"supersedes": [],
"answers": {
"architecture_risk": "no",
"public_contract": "no"
}
},
"approved_delta_digests": {}
},
{
"gate": "finalization",
"actor": "specsync:finalization",
"timestamp": 1790448323,
"digest": "bb3ac0fdd2087ebfddedd9515130f152ef1a3195880f0956afaa42e51db241f4",
"note": "Same-PR finalization closing digest"
}
],
"reopenings": []
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
id: accept-windows-refused-connection-wording-in-the-isolation-test
state: draft
state: archived
type: bug_fix
base_commit: c65af7f55d832475c877fb9032bc89da4bb685f3
---
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"schema_version": 2,
"change_id": "accept-windows-refused-connection-wording-in-the-isolation-test",
"implementation_commit": "b17675bb3457b75714b39d3e2cf76207f1a796e9",
"implementation_tree": "14f5f76c2eef89697e0316e57c9b9493b74cdbed",
"contract_digest": "4d3c64c5dd4d951b2b09fbd0e6463bc55c0d33f14a4eb7aca98775cfcf6d3694",
"workspace_digest": "aef38b6e4b761db015e6da5bbf7076e60db99d898b196639b976dbcba896e5a7",
"closing_digest": "bb3ac0fdd2087ebfddedd9515130f152ef1a3195880f0956afaa42e51db241f4",
"review_digest": "0745b7f9e0211f44d715b1fc117ca94e0da3ac3d0aaed38395cfe245a348a91a",
"finalization_digest": "1511e59e4eabfd4975a912abd52e28aabb2fe4d53c7edd9c064c66e5600d00aa",
"timestamp": 1790448323
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Lesson bundle — accept-windows-refused-connection-wording-in-the-isolation-test

Material for folding this change's lessons into the affected specs' `context.md`.
Synthesise from what actually happened below; do not restate the change description.

## What this change was

- **Title**: Accept Windows' refused-connection wording in the isolation test
- **Kind**: BugFix
- **Paths**: tests/isolation.rs
- **Acceptance**: default_temp_env_points_github_at_a_dead_port in tests/isolation.rs passes on Linux, macOS and Windows: it still asserts the default TempEnv GitHub base starts with http://127.0.0.1: and that the spawned templates search fails, and it recognizes the refusal as 'connection refused' (Linux, macOS) or Windows' WSAECONNREFUSED wording ('actively refused' / 'os error 10061'), so a genuine api.github.com failure still does not satisfy it; cargo test --locked is green on ubuntu-latest, macos-latest and windows-latest with both the ureq 3.3.0 lockfile on main and the ureq 3.4.2 lockfile the v1.8.0 release carries

## Evidence

- Verification commit: `b17675bb3457b75714b39d3e2cf76207f1a796e9`
- Base commit: `c65af7f55d832475c877fb9032bc89da4bb685f3`
- Verified by: `specsync check (no spec in scope)`

## From the change's context.md

# Context

## What led here

The v1.8.0 release PR (#532) went red on exactly one cell: `test (windows-latest)`,
in `tests/isolation.rs::default_temp_env_points_github_at_a_dead_port`:

```text
expected a refused local connection, got: error: searching github for template repos:
github api request failed: io: no connection could be made because the target machine
actively refused it. (os error 10061)
```

The same test is green on Windows on `main`. The difference is the lockfile: the release
bump moves `ureq` from 3.3.0 to 3.4.2. In 3.3.0, when every resolved address refused,
`ureq`'s TCP connector threw the OS error away and returned a synthesized
`io::Error::new(ConnectionRefused, "Connection refused")`, so every platform printed the
same English words. 3.4 keeps the last per-address error instead (`last_err` in
`unversioned/transport/tcp.rs`), so the message is now the OS's own:

| Platform | stderr on ureq 3.4.2 |
|---|---|
| Linux | `io: Connection refused (os error 111)` |
| macOS | `io: Connection refused (os error 61)` (observed locally) |
| Windows | `io: No connection could be made because the target machine actively refused it. (os error 10061)` (from the CI log) |

The test's two alternatives were `connection refused` and `127.0.0.1`. The Windows text
has neither, and `ureq` never puts the address in the message, so the test failed.
Nothing in fledge's behavior changed: the request was refused locally, as intended.

## Decisions

**Widen the wording, keep both halves of the proof.** The test exists to rule out a real
request to api.github.com. It does that in two halves, and both are kept unchanged in
strength: the base handed to the child starts with `http://127.0.0.1:`, and the failure is
a refusal. Only the set of words that count as "a refusal" grows, by the two stable parts
of WSAECONNREFUSED's message: `actively refused` and `os error 10061`. A generic
`contains("failed")` stays excluded, because a genuine api.github.com failure satisfies it.

**Match the message, not the error kind.** The test sees a spawned binary's stderr, not
an `io::Error`, so `ErrorKind::ConnectionRefused` is not observable here. Matching the OS
text is the only option at this boundary.

**Land on `main` first.** `main` is green today only because it still pins ureq 3.3.0.
Any lockfile refresh, the release's included, brings in 3.4 and the failure. Fixing it
on `main` lets the release PR rebase onto a test that is already correct, instead of
carrying a test change inside a release commit.

## Out of scope

- Dropping or skipping the Windows matrix cell. corvid-agent offered it as an
alternative. It would hide the signal instead of fixing a test that is wrong.
- The `127.0.0.1` alternative in the stderr assertion. It predates this change and is
unreachable with ureq, but removing it is a separate tightening.

## From the change's testing.md

# Testing

## Automated

`tests/isolation.rs::default_temp_env_points_github_at_a_dead_port` is the only test in
scope. It runs in CI's `cargo test --verbose --locked` on `ubuntu-latest`,
`macos-latest` and `windows-latest`.

## What was verified

| Check | Result |
|---|---|
| `fledge run test -- --test isolation` on `main`'s lockfile (ureq 3.3.0), macOS | 4 passed |
| Same, on the v1.8.0 release lockfile (ureq 3.4.2), macOS | 4 passed |
| Spawned binary stderr, ureq 3.3.0, macOS | `io: Connection refused` (synthesized by ureq) |
| Spawned binary stderr, ureq 3.4.2, macOS | `io: Connection refused (os error 61)` (the OS's text) |
| Windows stderr, ureq 3.4.2 (#532 CI log) | contains `actively refused` and `os error 10061`, now accepted |
| `test` on all three OSes, #535 (ureq 3.3.0) | green, CI run 36257383427 |
| `test` on all three OSes, ureq 3.4.2 | green, CI run 36257571327 (`workflow_dispatch` probe: `main` + this fix + #532's release commit). The Windows log shows `Compiling ureq v3.4.2` and `default_temp_env_points_github_at_a_dead_port ... ok` |
| `test` on all three OSes, the v1.8.1 release PR #536 (ureq 3.4.2) | green, CI run 36260828952 |

## Acceptance signals

- `test (windows-latest)` is green on the rebased release PR, which carries ureq 3.4.2.
- `test (ubuntu-latest)`, `test (macos-latest)` and `test (windows-latest)` stay green on
`main`'s ureq 3.3.0 lockfile.

## Rejection signals

- A run that reached api.github.com and failed there must still fail the test. The
loopback assertion on `env.github_api_base()` is unchanged, and no accepted phrase
(`connection refused`, `actively refused`, `os error 10061`) appears in a GitHub HTTP
error or a DNS failure.
- A generic "the command failed" must not be enough. No new alternative matches
`failed` or `error` alone.

## Where these lessons go

This change declared no affected specs, so there is no module context to fold into.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"schema_version": 1,
"reviews": [
{
"schema_version": 2,
"change_id": "accept-windows-refused-connection-wording-in-the-isolation-test",
"reviewer": "user:0xLeif",
"provenance": {
"schema_version": 1,
"provider": "github_actions_check",
"required_check": "SpecSync scoped review"
},
"verdict": "pass",
"implementation_commit": "b17675bb3457b75714b39d3e2cf76207f1a796e9",
"contract_digest": "4d3c64c5dd4d951b2b09fbd0e6463bc55c0d33f14a4eb7aca98775cfcf6d3694",
"execution_digest": "8b8bac8ff77bc766d787bdf5cee8255bd499a4d1f59a24e82a618232c5d4c588",
"workspace_digest": "aef38b6e4b761db015e6da5bbf7076e60db99d898b196639b976dbcba896e5a7",
"timestamp": 1790448304
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"schema_version": 2,
"change_id": "accept-windows-refused-connection-wording-in-the-isolation-test",
"reviewer": "user:0xLeif",
"provenance": {
"schema_version": 1,
"provider": "github_actions_check",
"required_check": "SpecSync scoped review"
},
"verdict": "pass",
"implementation_commit": "b17675bb3457b75714b39d3e2cf76207f1a796e9",
"contract_digest": "4d3c64c5dd4d951b2b09fbd0e6463bc55c0d33f14a4eb7aca98775cfcf6d3694",
"execution_digest": "8b8bac8ff77bc766d787bdf5cee8255bd499a4d1f59a24e82a618232c5d4c588",
"workspace_digest": "aef38b6e4b761db015e6da5bbf7076e60db99d898b196639b976dbcba896e5a7",
"timestamp": 1790448304
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
"title": "Accept Windows' refused-connection wording in the isolation test",
"description": "Accept Windows' refused-connection wording in the isolation test",
"kind": "bug_fix",
"state": "draft",
"state": "archived",
"canonical_applied": true,
"base_commit": "c65af7f55d832475c877fb9032bc89da4bb685f3",
"created_at": 1790441579,
"updated_at": 1790441589,
"updated_at": 1790448360,
"affected_specs": [],
"affected_paths": [
"tests/isolation.rs"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,10 @@ artifact: tasks
- [x] Accept `actively refused` / `os error 10061` alongside `connection refused`, keeping
the loopback-base assertion and excluding a bare `failed`
- [x] Run the isolation tests on both lockfiles locally (macOS)
- [ ] `test (windows-latest)` green on this PR (ureq 3.3.0)
- [ ] `test (windows-latest)` green on the rebased #532 (ureq 3.4.2)
- [x] `test (windows-latest)` green on #535 (ureq 3.3.0), in CI run 36257383427
- [x] `test (windows-latest)` green with ureq 3.4.2, in CI run 36257571327: a
`workflow_dispatch` probe of `main` + this fix + #532's release commit rebased
onto it
- [x] `test (windows-latest)` green on the release PR itself, in CI run 36260828952. That
PR is #536 (v1.8.1), which replaced the closed #532 because 1.8.0 was already on
crates.io; it carries ureq 3.4.2 on top of this change
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ scope. It runs in CI's `cargo test --verbose --locked` on `ubuntu-latest`,
| Spawned binary stderr, ureq 3.3.0, macOS | `io: Connection refused` (synthesized by ureq) |
| Spawned binary stderr, ureq 3.4.2, macOS | `io: Connection refused (os error 61)` (the OS's text) |
| Windows stderr, ureq 3.4.2 (#532 CI log) | contains `actively refused` and `os error 10061`, now accepted |
| `windows-latest` on this PR | runs with `main`'s ureq 3.3.0, must stay green |
| `windows-latest` on the rebased #532 | runs with ureq 3.4.2, the case this change fixes |
| `test` on all three OSes, #535 (ureq 3.3.0) | green, CI run 36257383427 |
| `test` on all three OSes, ureq 3.4.2 | green, CI run 36257571327 (`workflow_dispatch` probe: `main` + this fix + #532's release commit). The Windows log shows `Compiling ureq v3.4.2` and `default_temp_env_points_github_at_a_dead_port ... ok` |
| `test` on all three OSes, the v1.8.1 release PR #536 (ureq 3.4.2) | green, CI run 36260828952 |

## Acceptance signals

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
"schema_version": 1,
"attempts": [
{
"timestamp": 1790447742,
"commit": "e89b8d02a6d50bfd8c4be59dbeba8ed0b752eedc",
"contract_digest": "4d3c64c5dd4d951b2b09fbd0e6463bc55c0d33f14a4eb7aca98775cfcf6d3694",
"execution_digest": "8b8bac8ff77bc766d787bdf5cee8255bd499a4d1f59a24e82a618232c5d4c588",
"workspace_digest": "aef38b6e4b761db015e6da5bbf7076e60db99d898b196639b976dbcba896e5a7",
"passed": true,
"commands": [
{
"command": "specsync check (no spec in scope)",
"success": true,
"exit_code": 0
}
],
"requirement_ids": []
},
{
"timestamp": 1790447746,
"commit": "ac986196727276296d1ac6dd2550800b0da64759",
"contract_digest": "4d3c64c5dd4d951b2b09fbd0e6463bc55c0d33f14a4eb7aca98775cfcf6d3694",
"execution_digest": "8b8bac8ff77bc766d787bdf5cee8255bd499a4d1f59a24e82a618232c5d4c588",
"workspace_digest": "aef38b6e4b761db015e6da5bbf7076e60db99d898b196639b976dbcba896e5a7",
"passed": true,
"commands": [
{
"command": "specsync check (no spec in scope)",
"success": true,
"exit_code": 0
}
],
"requirement_ids": []
},
{
"timestamp": 1790447746,
"commit": "b17675bb3457b75714b39d3e2cf76207f1a796e9",
"contract_digest": "4d3c64c5dd4d951b2b09fbd0e6463bc55c0d33f14a4eb7aca98775cfcf6d3694",
"execution_digest": "8b8bac8ff77bc766d787bdf5cee8255bd499a4d1f59a24e82a618232c5d4c588",
"workspace_digest": "aef38b6e4b761db015e6da5bbf7076e60db99d898b196639b976dbcba896e5a7",
"acceptance_input_digest": "7ec19b5b4b21ece765d089a32be26cb8f7f527b53e8435fcdfc36b8904e12568",
"acceptance_manifest": {
"schema_version": 1,
"entries": [
{
"path": "tests/isolation.rs",
"kind": "file",
"mode": 33188,
"payload_digest": "df7a1ed803764c0869a3ff45305058a370499a585f227ca8da20261a32df63cd",
"entry_digest": "e9ec7c57075f465c0e41585798e9a6ccf7ed4cb527e3306cf1bb32ab432959d9",
"owners": [
"@exact:test"
]
}
]
},
"passed": true,
"commands": [
{
"command": "specsync check (no spec in scope)",
"success": true,
"exit_code": 0
}
],
"requirement_ids": []
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"timestamp": 1790447746,
"commit": "b17675bb3457b75714b39d3e2cf76207f1a796e9",
"contract_digest": "4d3c64c5dd4d951b2b09fbd0e6463bc55c0d33f14a4eb7aca98775cfcf6d3694",
"execution_digest": "8b8bac8ff77bc766d787bdf5cee8255bd499a4d1f59a24e82a618232c5d4c588",
"workspace_digest": "aef38b6e4b761db015e6da5bbf7076e60db99d898b196639b976dbcba896e5a7",
"acceptance_input_digest": "7ec19b5b4b21ece765d089a32be26cb8f7f527b53e8435fcdfc36b8904e12568",
"acceptance_manifest": {
"schema_version": 1,
"entries": [
{
"path": "tests/isolation.rs",
"kind": "file",
"mode": 33188,
"payload_digest": "df7a1ed803764c0869a3ff45305058a370499a585f227ca8da20261a32df63cd",
"entry_digest": "e9ec7c57075f465c0e41585798e9a6ccf7ed4cb527e3306cf1bb32ab432959d9",
"owners": [
"@exact:test"
]
}
]
},
"passed": true,
"commands": [
{
"command": "specsync check (no spec in scope)",
"success": true,
"exit_code": 0
}
],
"requirement_ids": []
}
Loading
Loading