Skip to content

Lay the repository out, and give a fresh clone two commands (#13) - #182

Merged
iderex merged 1 commit into
mainfrom
issue-13-the-layout-and-the-two-commands-2
Aug 25, 2026
Merged

Lay the repository out, and give a fresh clone two commands (#13)#182
iderex merged 1 commit into
mainfrom
issue-13-the-layout-and-the-two-commands-2

Conversation

@iderex

@iderex iderex commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

The issue this belongs to

#13

Named rather than closed. The third done-condition is that the gate workflows
added in this milestone invoke these same two commands, and no such workflow
exists yet; #15 is where the first one lands. Everything else in the condition is
met and shown below.

What changed

A crate, a layout, two commands and one guard.

One directory under src/ per thing
0003 says the core owns, so
that the boundary is visible in the tree rather than only in a document:
src/server/, src/session/, src/cache/, src/artwork/, src/playback/ and
src/measurement/. Two directories sit beside those six and are not concerns from
that record, and each says so in its own first paragraph: src/failure/ for the
error vocabulary the six map onto, and src/diagnostics/ for the sink a client
supplies.

There is no behaviour anywhere in it. Every type is a name carrying the statement
0009 makes about its kind, and each names the issue that owns what it will do.

README.md gains the two commands, a sentence on what a fresh clone needs
installed, and the arrangement above. One sentence in it is a correction rather
than an addition. What it said before:

What shared means technically is the first maintainer decision and the plan
states the options with their costs rather than choosing one.

Entry 2 of #1 was answered on 2026-08-24 and 0011 recorded it, so that sentence
had stopped being true.

The means, and why it fits

Rust with cargo, because
0011
records that choice and this is the first change that had to make it real. Nothing
here adds a language, a runtime or a dependency beyond what that record already
priced: the manifest declares no dependencies, the formatter and the analyser are
components of the toolchain, and the suite this change starts is the one every
later issue in M2 uses.

What failure it prevents

The one this issue names: a clone that builds nothing and runs nothing, and a
layout that arrives as eleven accidents instead of one decision.

The sharper one is 0009's, and it is a failure that would have been silent. That
record states its reentrancy and thread-safety rules per kind of object because
there was no type to attach them to, and says the names arrive with #11 and #13.
A layout satisfying every word of this issue could still leave those statements
attached to nothing: the record goes on being true, and the reader who meets a
handle in the tree meets no statement about which thread they may call it from.
The statements are attached to the types, and the suite refuses a change that
breaks one.

Evidence

The two commands README.md names, run from a tree with no build state, at the
commit being pushed:

rm -rf target
cargo build --locked --all-targets
   Compiling flowfin-core v0.0.0 (G:\Github\core)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 14.17s

cargo test --locked
     Running unittests src\lib.rs
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running tests\thread_statements.rs
running 7 tests
test a_decoded_image_is_safe_from_any_thread ... ok
test a_query_result_is_safe_from_any_thread ... ok
test the_secret_store_a_client_supplies_is_safe_from_any_thread ... ok
test the_byte_store_a_client_supplies_is_safe_from_any_thread ... ok
test the_core_handle_is_safe_from_any_thread ... ok
test the_diagnostics_sink_a_client_supplies_is_safe_from_any_thread ... ok
test a_session_handle_is_safe_from_any_thread ... ok
test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Doc-tests flowfin_core
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

The toolchain both were run on:

rustc -vV
rustc 1.97.0 (2d8144b78 2026-07-07)
host: x86_64-pc-windows-msvc
release: 1.97.0
LLVM version: 22.1.6

The analyser and the formatter are clean, which matters because #17 and #18 will
turn each into a check and a backlog on the first day is a backlog forever:

cargo clippy --all-targets -- -D warnings
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 16.89s

cargo fmt --check
(no output, exit 0)

The lockfile the two commands assert against is committed and holds one package,
which is this one:

cat Cargo.lock
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4

[[package]]
name = "flowfin-core"
version = "0.0.0"

Every path README.md names resolves. The whole-tree document verb does not
finish inside nine minutes on this machine, so its own rules were applied to that
one document through the script's own functions rather than a second copy of
them, and the run in this pull request is the one over the whole tree:

universe: 107 paths
== README.md
COUNT   16      0       0

Sixteen named paths resolved, none excused, no refusal.

What a guard here refuses, and the proof it bites

tests/thread_statements.rs refuses a type that stops being safe to use from any
thread, for each of the kinds 0009 makes that statement about. It refuses in two
directions and both were proven before this landed.

A field that is not thread-safe, added to the core handle:

// src/lib.rs, _private: () replaced by _private: std::cell::Cell<u32>
cargo build --all-targets
error[E0277]: `Cell<u32>` cannot be shared between threads safely
  --> src\lib.rs:80:18
   |
80 |     any_thread::<Core>();
   |                  ^^^^ `Cell<u32>` cannot be shared between threads safely
   = help: within `Core`, the trait `Sync` is not implemented for `Cell<u32>`
note: required by a bound in `any_thread`
error: could not compile `flowfin-core` (lib) due to 1 previous error

The bound dropped from a client-supplied store, which is the direction a check
written only against an implementor would miss:

// src/cache/mod.rs, `pub trait ByteStore: Send + Sync {}` replaced by `pub trait ByteStore {}`
cargo test
error[E0277]: `dyn ByteStore` cannot be sent between threads safely
  --> tests\thread_statements.rs:57:32
   |
57 |     const _: () = any_thread::<dyn ByteStore>();
   |                                ^^^^^^^^^^^^^ `dyn ByteStore` cannot be sent between threads safely
   = help: the trait `Send` is not implemented for `dyn ByteStore`

And green again with the violation removed, which is the run in the evidence
section above.

What the guard is worth today is stated in the crate documentation rather than
implied: the types hold nothing, so no assertion can fail on the bytes in this
tree. It bites on the first field, which is the change it exists for, and the two
runs above are that change made deliberately.

What this does not cover

The third done-condition of #13. No gate workflow added in this milestone exists,
so nothing here proves that the gate runs these two commands rather than variants
of them. #15 is the first one and this issue stays open until then.

Three of 0009's statements are not checked by anything here and the test file says
so in its own first paragraph: that the secret store is called from one lane only
and never concurrently for one session, that a sink must not block, and that a
sink must not call back into the core. Those are properties of the caller rather
than of the type. #117 is where they are meant to be observed, and it has its own
bounds.

Nothing was built for any target other than this host, and nothing cross-compiled.
Which triples the gate covers is #113.

No version is pinned. #14 owns that, and README.md says a current stable
toolchain builds this rather than naming a digit that would then exist in two
places.

src/failure/ and src/diagnostics/ hold no type yet. The failure vocabulary is
#4 and #37 and the diagnostics interface is #100, and inventing either here would
be deciding them in the file that was meant to hold them.

The Send + Sync bound on a client-supplied trait is not a statement that the
core calls it concurrently. 0009's sentence is the rule for each, and the doc
comment on the secret store says the opposite of concurrent access explicitly so
that the bound is not read as permission.

Who has read it

Nobody but me. There is no second reader on this board tonight, and the evidence
above stands in place of one.

A clone could build nothing and run nothing. It can now do both, with the two
commands written in README.md and no state left by a previous build needed for
either.

One directory under src/ per thing 0003 says the core owns, so the boundary is in
the tree rather than only in a document: server, session, cache, artwork,
playback and measurement. Two directories sit beside those six and are not
concerns from that record; each says so in its own first paragraph. failure holds
the error vocabulary the six map onto, and diagnostics holds the sink a client
supplies, which is there because 0009 states a thread rule for it and a rule with
no name to attach to is a rule a reader meets nowhere.

There is no behaviour. Every type is a name carrying the statement 0009 makes
about its kind and nothing else, and each names the issue that owns what it will
do.

The half that is a guard rather than a layout is 0009's obligation. That record
states its reentrancy and thread-safety rules per kind of object because there was
no type to attach them to, and says the names arrive with #11 and #13. The
statements are attached where a reader meets each type, and
tests/thread_statements.rs refuses a change that breaks one: "safe from any
thread" is a compile-time bound, checked from outside the crate so that it asks
the same question a client asks, and checked on the trait object for a
client-supplied store so that dropping the bound from the trait is caught rather
than only a bad implementor. Both directions were proven to bite before this
landed, and the proofs are in the pull request body.

What that bound is worth today is stated in the crate documentation rather than
implied: the types hold nothing, so no assertion can fail on these bytes. It bites
on the first field.

The package is called flowfin-core rather than core. The standard library owns
that name, and a local crate carrying it makes every path that means the standard
one ambiguous at the first use.

One sentence in README.md was a correction rather than an addition. What it said
before:

> What shared means technically is the first maintainer decision and the plan
> states the options with their costs rather than choosing one.

Entry 2 of #1 was answered on 2026-08-24 and 0011 records it, so that sentence had
stopped being true; it now names the answer and links the record.

Signed-off-by: Nils Lehnen <30603423+iderex@users.noreply.github.com>
@iderex iderex added documentation Improvements or additions to documentation architecture Shape of the core: boundaries, interfaces, contracts labels Aug 25, 2026
@iderex iderex self-assigned this Aug 25, 2026
@iderex
iderex merged commit bf2b5af into main Aug 25, 2026
12 checks passed
@iderex
iderex deleted the issue-13-the-layout-and-the-two-commands-2 branch August 25, 2026 04:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

architecture Shape of the core: boundaries, interfaces, contracts documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant