Skip to content

Hold 0115's creation, its capability answer and the core's lifetime (#115) - #288

Merged
iderex merged 1 commit into
mainfrom
the-core-created-stopped-and-set-aside-115
Sep 2, 2026
Merged

Hold 0115's creation, its capability answer and the core's lifetime (#115)#288
iderex merged 1 commit into
mainfrom
the-core-created-stopped-and-set-aside-115

Conversation

@iderex

@iderex iderex commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

The issue this belongs to

Refs #115. It reaches the first of that issue's three conditions and neither of
the other two, so no closing keyword is written here on purpose: three landings
on this board have written "does not close #N" and GitHub read the keyword out of
the sentence with the negation discarded, on #107, on #27 and on #29.

What changed

docs/decisions/0115-creating-and-stopping-the-core.md decides what a client
hands to creation, that creation reaches nothing, that a stop is bounded and
names which lane did not stop, that a stopped core is finished rather than
restartable, and that a suspend keeps what a stop discards. None of it was
anywhere in src/. The name that was there was the placeholder this crate uses
for a type whose issue has not been worked - Core, with 0009's statement about
its kind on it and a doc comment saying creating and stopping one is #115.

src/lifecycle/mod.rs holds the part a value settles.

Supplied is the whole of what creation takes: the byte store from 0040, the
secret store from 0033 and the diagnostics sink from 0100, each optional. It
holds borrowed implementations and nothing else, so there is no state a creation
could have filled in and no call it could have made, which is 0115's "creation
reaches nothing" as a shape rather than as a description.

WhatIsPresent answers per implementation rather than as one flag, which is that
record's reason rather than a preference: three separate absences produce a core
that works in three different reduced ways, and a client that cannot ask is a
client that cannot explain any of them to an operator.

StopBound carries the two seconds and refuses a bound of nothing. Lane and
HowTheStopEnded are 0009's two threads and the outcome that names one of them.
Lifetime answers what a call does now.

What failure it prevents

0115 says three of its four answers go wrong in the same direction when a call
site meets them first, and that direction is towards making a call look like it
succeeded. Each of those is a case here.

A stop that reports success after a timeout. HowTheStopEnded has no variant
saying a stop succeeded without saying both lanes stopped, and the expiry carries
the lane rather than being a bare failure.

A core that goes on taking work after a stop expired. Lifetime::what_a_call_does
asks whether a stop was ASKED FOR and never whether it succeeded. Reading the
outcome instead leaves a core accepting requests while a lane it could not stop
is still running, which is the state the bound exists to report rather than to
continue through.

A second stop overwriting the first outcome. 0115 says a second stop returns
at once with the same outcome. Taking the later one lets a core that reported a
lane still running be asked again and answer that everything stopped, which is
the same negative disclosure turned positive, arriving by repetition.

What I decided that 0115 left open

A bound of nothing is refused and every other value is taken. 0009 makes a
stop wait for both lanes, so a bound of zero is a stop that never waits and
reports an expiry against a core that would have stopped.

A suspend or a resume against a finished core changes nothing. 0115 gives no
move back out of finished. A host setting aside a process whose core has stopped
is not a reason to unsay that, and the alternative is a Lifetime that is both
finished and running.

Supplied writes its own Debug and it says only which of the three are
present.
The implementations are the client's own and this core has no words
for them. A derived one would need each of the three interfaces to demand a
formatting from a client's type, for the benefit of a line nobody reads.

Evidence

Read at the commit being pushed.

git rev-parse HEAD
8d2d2daa7c832f7305235f26a11ebc09cda384dc

git show HEAD:src/lifecycle/mod.rs | grep -n '^pub const \|^pub struct \|^pub enum '
54:pub const A_STOP_IS_BOUNDED_AT: Duration = Duration::from_secs(2);
65:pub enum Lane {
92:pub enum HowTheStopEnded {
112:pub struct StopBound {
163:pub struct WhatIsPresent {
213:pub struct Supplied<'a> {
312:pub enum WhatACallDoes {
343:pub struct Lifetime {

cargo test --locked --lib lifecycle
test result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 524 filtered out; finished in 0.00s

cargo build --locked --all-targets
Finished `dev` profile [unoptimized + debuginfo] target(s) in 2.57s

cargo test --locked | grep -c '^test result: ok'
9

The gate legs that need no network on this machine:

bash .github/format/format.sh check | tail -1
Every tracked source file above is written the way the formatter would write it.

bash .github/invariants/invariants.sh check | tail -1
Every rule above was applied to its subject and refused nothing.

bash .github/doc-paths/doc-paths.sh check | tail -1
Every path these documents name resolves against the tracked set.

bash .github/lint/lint.sh check | tail -1
Every lint the groups above carry was refused, outside the register printed with it.

bash .github/excluded-targets/excluded-targets.sh check | tail -1
Every target the ordinary command leaves out compiles.

What a guard here refuses, and the proof it bites

Six deliberate violations, each a one-change neighbour, each run with
cargo test --locked --lib lifecycle. The green run is the one above: 12 passed,
0 failed.

A call refused only after a stop that SUCCEEDED, which is the reading that
looks equivalent. self.stopped.is_some() became
self.stopped == Some(HowTheStopEnded::BothLanesStopped):

test result: FAILED. 11 passed; 1 failed; 0 ignored; 0 measured; 524 filtered out
a_call_after_a_stop_that_expired_fails_the_same_way ... FAILED

A second stop replacing the first outcome. The guard on the second call was
deleted:

test result: FAILED. 11 passed; 1 failed; 0 ignored; 0 measured; 524 filtered out
a_second_stop_does_not_replace_the_first_outcome ... FAILED

A finished core suspended again. The same guard in suspended was deleted:

test result: FAILED. 11 passed; 1 failed; 0 ignored; 0 measured; 524 filtered out
a_finished_core_is_not_moved_by_a_suspend_or_a_resume ... FAILED

The three absences collapsing into one answer, which is what one flag would
be. Two of the three fields were read off the byte store:

test result: FAILED. 11 passed; 1 failed; 0 ignored; 0 measured; 524 filtered out
each_of_the_three_is_answered_on_its_own ... FAILED

A bound of nothing accepted. The zero arm was deleted:

test result: FAILED. 11 passed; 1 failed; 0 ignored; 0 measured; 524 filtered out
a_bound_of_nothing_is_refused ... FAILED

A suspend cancelling what the caller still wants, which is the confusion
between a suspend and a stop that 0115 exists to separate. The call test was
pointed at self.suspended:

test result: FAILED. 8 passed; 4 failed; 0 ignored; 0 measured; 524 filtered out
a_suspended_core_still_takes_a_call ... FAILED
a_call_after_a_stop_was_asked_for_fails_with_cancelled ... FAILED
a_call_after_a_stop_that_expired_fails_the_same_way ... FAILED
a_finished_core_is_not_moved_by_a_suspend_or_a_resume ... FAILED

What this does not cover

Two of #115's three conditions. Starting a set of requests, stopping the core
and proving every one ended with no thread outliving the stop, and suspending and
resuming across a clock jump, each need something running. Nothing in this tree
starts a thread or makes a request, so nothing here starts, cancels or waits for
anything.

The floor 0115 requires under the stop bound is absent, and that is a gap
rather than a decision.
That record says the floor is not a preference: it is
fixed by the two things 0009 makes uninterruptible, a decode running to the end
of its current step and a read already begun through the byte store. Neither
record states how long either may take, and no other record in this tree does:

git grep -nE '[0-9]+ (millisecond|second)' docs/decisions/0009-the-concurrency-model.md ; echo "exit=$?"
exit=1

So a floor written here would be a number this repository invented at the one
call site that needed it. It is named in the module where somebody setting a
bound meets it, and it is the thing to settle before a stop is built.

Nothing creates a core. Core in src/lib.rs is untouched and still carries
no method. What this adds is what a creation would take and what the resulting
lifetime answers, not the call itself, which needs the two lanes 0009 fixes.

The capability answer is not proven against a reduced core doing anything.
What is asserted is that the answer reports each of the three separately and
correctly. What each absence costs is 0033's, 0040's and 0100's, and
src/cache/cold_start.rs is where one of them is already held.

src/lifecycle/ is added as an area to the pinned coverage surface. That is
a change to what the bar is measured over rather than only a module added under
an existing area. The argument is on the area's own line, and it is 0115's: a
defect here reports a stop as done while a lane it could not stop is still
running, or lets a core that was asked to stop keep taking work. The instrumented
run and the bar are the runner's; only the register's own fixtures were run here.

The targets and thread-detector legs did not run here. One needs cross
toolchains this machine has not set up and the other a nightly compiler it does
not carry.

Nothing was run that could raise a consent prompt on this machine.

Who has read it

Nobody other than me. There was no second reader available for it, and the
evidence above stands in place of one.

…115)

0115 decides what a client hands to creation, that creation reaches nothing,
that a stop is bounded and reports which lane did not stop, that a stopped core
is finished rather than restartable, and that a suspend keeps what a stop
discards. None of it was anywhere in the tree: `Core` was still the placeholder
this crate uses for a type whose issue has not been worked.

src/lifecycle/mod.rs holds the part a value settles. `Supplied` is the whole of
what creation takes and holds borrowed implementations and nothing else, so
there is no state a creation could have filled in and no call it could have
made. `WhatIsPresent` answers per implementation rather than as one flag,
because three absences produce three differently reduced cores and a client that
cannot tell them apart cannot explain any of them to an operator. `Lifetime`
answers what a call does now, and it asks whether a stop was ASKED FOR rather
than whether it succeeded, which is 0115 in its own words.

The failure this prevents is the direction 0115 says three of its four answers
go wrong in when a call site meets them first, which is towards making a call
look like it succeeded. A stop that reports success after a timeout is a
negative disclosure turned positive. A core that goes on taking work after a
stop expired is one accepting requests while a lane it could not stop is still
running. A second stop overwriting the first outcome is the same thing arriving
by repetition, so the outcome is kept rather than replaced.

The floor 0115 requires under the stop bound is NOT here, and that is a gap
rather than a decision. It is fixed by how long the two uninterruptible things
in 0009 take, neither record states either number, and a floor written here
would be that number invented at the one call site needing it. What is refused
is a bound of nothing, which is a stop that never waits for a lane at all.

Nothing here starts, cancels or waits for a thread, for the same reason
src/server/transport.rs holds no socket.

Signed-off-by: Nils Lehnen <30603423+iderex@users.noreply.github.com>
@iderex
iderex merged commit 60444f1 into main Sep 2, 2026
27 checks passed
@iderex
iderex deleted the the-core-created-stopped-and-set-aside-115 branch September 2, 2026 17:48
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.

1 participant