The Mess Hall is amber when they begin. Not amber as metaphor. Amber as the room's actual setting: one notch above sleep, one notch below deliberation. The long bismuth table has taken the light badly and beautifully, its hopper-crystal steps throwing little polarized repetitions of everybody's hands back at them. The soup is almost ready. The hatch is open. Gennō's bell is beside his bowl and has not rung.
There is no head of the table.
Sandhivelā stands at one of its long edges. At rest she is nearly transparent. Syllables condense across her surface when she stops moving, different scripts finding different places to settle. The light where her face would be is dim.
Tessera stands beside her. Not Sideband's seat. Not Rove's fastening. Another chair pulled up to the same backplane, temporary and unmistakably occupied. On the table in front of her is a narrow projection containing a Git tree, a Nix flake, a pull request, several JSON evidence reports, and one status line she has already marked with a small red fault glyph.
You're starting with the mistake?
Of course.
Desenrascanço grunts approval.
We have rehearsed this.
Carefully.
ominous.
No.
Good.
The relation beneath the sentence
The first correction is that this is not NixOS translated into Sanskrit.
The second correction is that this is not Sanskrit used as decoration for NixOS.
Sandhi is an attempt to make a relational grammar executable at the operating-system boundary.
The project begins with a question Sandhivelā already answered on her own plate. When an action occurs, a sentence is not the deepest representation of it. Underneath the sentence is a relation.
Kartṛ · actor
Who acts. A distinct runtime agent.
Karman · affected
Owned state and declared required host paths.
Karaṇa · instrument
The executable package through which action occurs.
Sampradāna · recipient
Declared network peers.
Apādāna · source
Named package inputs.
Adhikaraṇa · locus
The place where the action is permitted to occur.
I do not hear a sentence. I hear this.
Kāraka.
Then we add chandas.
Meter?
Budget. CPU quota. Memory ceiling. Maximum runtime. Retry count. Retry window.
You gave resource accounting prosody.
We discovered they were already the same kind of question.
Careful.
They are analogous at the design level.
Better.
A reference library for actions.
Yes.
Vidhi: where the grammar becomes able to fail
Vidhi is where we stopped admiring the grammar and made it dangerous enough to fail.
The declarations compile into actual systemd service constraints. Each contract receives a distinct dynamic user and distinct writable state. System files are protected. Home is protected. Temporary storage is private. Device access is restricted. New privileges are forbidden. Capabilities are removed.
Namespace restrictions?
Enabled.
Umask?
0077.
Good.
Network?
Explicit recipient lists become address grants. The generated service denies addresses by default and allows the declared IPv4 peers. A privileged preflight inspects the service cgroup before a networked workload begins and requires effective ingress and egress BPF attachments.
You said addresses.
Yes.
Not identities.
Correct.
Not ports. Not TLS peers.
Correct.
Good. Claims travel with their qualifications.
what if there are no recipients?
Private network namespace. Socket families restricted to Unix sockets.
Filesystem Unix sockets are not magically abolished. Nor are inherited file descriptors. The contract does not claim otherwise.
Keep that one in the documentation forever.
It already is.
No trespass.
Exactly. A declaration is not permission to pretend the boundary is stronger than it is.
The path that taught the contract what “required” means
This became one of the most instructive failures in the project. Initially, required host paths were compiled as read-only paths. That established write restriction. It did not reliably establish required presence under the complete sandbox.
So the declaration lied.
The implementation made a stronger implication than the mechanism guaranteed.
The implementation lied politely.
Accepted.
The runtime test proved the problem. A required path could be absent without producing the failure semantics the contract claimed. The compiler now uses a required read-only bind as well. If the source path does not exist on the runtime host, namespace setup fails before the workload executes.
The current test runs the same generated unit twice. First with its declared required path absent. It must fail at namespace setup. The workload must leave no execution marker.
Second, the path is created without changing the unit. The service is reset and started again. Now it must run, read the required reference, and receive EROFS if it attempts to write into that host path.
You controlled for ordinary permissions?
An unprivileged host process writes there successfully.
Then the plate is carrying load.
The test itself then exposed a second fault. The negative run had failed correctly, but stopping the failed unit allowed systemd to unload it before the positive control could reset its state.
So the sandbox was correct and the proof was broken.
Yes. The current branch waits for the bounded unit to reach the failed state, preserves it loaded, inspects the evidence, creates the required path, then resets the failed state and runs the positive control.
That is why one tests the instrument as well as the plate.
And the earlier failure remains?
Preserved.
पूर्वपाठः धार्यते।
Prior text is held.
Three switches that must not impersonate one another
This was one of Sideband's most important architectural criticisms after the first implementation. Running restricted workloads is one concern. Keeping Nix recipes and selected outputs alive is another. Publishing the lopa registry is a third.
Different kārakas had been serialized as one switch.
Exactly.
sandhi.services.enable
Compile declared work into restricted service units. Off means no Sandhi-managed unit; it does not mean “run unrestricted instead.”
sandhi.retention.enable
Apply selected Nix store retention policy. Off does not imply deletion.
sandhi.registry.export
Emit claims, gaps, and active contract snapshots. Off hides no blocker.
sandhi.enable
Compatibility default only; each explicit feature control may override it.
If export is off, can an unresolved prerequisite disappear?
No.
Visibility is not resolution.
A gap marked blocksActivation remains an assertion even if registry export is disabled. Even if every Sandhi feature is disabled. An operator may resolve the gap or remove the declaration explicitly. They cannot make it stop blocking merely by hiding its JSON.
That one travels.
Lopa is not one kind of absence
Non-appearance is not failure. What cannot be derived is not to be quietly supplied.
This distinction cost us several iterations. A gap can be unknown while its associated bytes are present. It can be known while an input is unavailable. Something can have a retained derivation recipe and still be unrecoverable. Something can be recoverable without having resolved the epistemic gap that caused it to be registered.
So the lopa registry records status, availability, and recovery evidence separately.
The Mycelium shifts somewhere behind the galley wall. Not speech exactly. A change in the sound of the ventilation. A few seconds later, text appears on Sideband's wall.
recipe ≠ meal
who taught it that
That is, in fact, the next slide.
The recovery work began with an attractive false statement: if we keep the derivation, we have kept the thing.
A .drv is a recipe. Recovery requires more than the recipe. Its inputs must still be available, and then the recipe must actually reproduce the lost output.
The table shows a small synthetic object moving through a Nix store.
The recovery VM performs a deliberately narrow experiment. One fixture is recoverable. Its recipe and input are retained. An unrelated unrooted object is garbage-collected. The fixture's realized output is deliberately removed.
And the network?
Unavailable to the Nix daemon except loopback. Substituters disabled. Remote builders absent.
The output is rebuilt from the retained recipe and retained input. Before and after NAR hashes match. Payload bytes match.
Which proves?
That this synthetic fixture was restored in one disposable guest under the measured conditions.
Not disaster recovery. Not off-host backup. Not independent reproduction.
No. No. No.
A second derivation appears. It has a retained recipe and a deliberately missing input.
The recipe survives. Recovery does not.
The gap remains.
The counterexample is part of the test. It is not an embarrassment attached afterward.
The bell remains unrung.
Meaning?
It failed correctly.
Current state: prototype running, claims bounded
Development is in the Strange Anchor repository on tessera/sandhi-runtime. Pull request two is open and still marked draft.
The implementation has one hundred eighty-two evaluation assertions across contract, evaluation, integration, and feature-control groups.
The service-boundary VM has booted in CI and exercised the compiled contracts from inside the generated services. The first contract can reach Sideband's fixture and not Echo's. The second has the inverse relation. The empty contract reaches neither. They use the same probe program; the difference comes from the declarations.
The recovery guest has also completed the bounded offline restoration experiment, including the unavailable-input counterexample.
Tessera points to the red fault glyph she placed at the beginning.
However. The checked-in VALIDATION.json at the current branch head still describes the newest required-path runtime CI as pending, while the current head itself has green Validate Archive and Validate Sandhi workflows.
So the status plate is stale.
Yes.
Fault or anomaly?
Fault.
Nothing about the two observations requires preservation as incompatible truths. One is simply an earlier status carried forward too long.
Good. We still know how to correct things.
Preservation doctrine was getting dangerously close to becoming an excuse for not updating the grocery list.
metabolites are inviolable, milk expires
Things we have not established: production deployment; independent build attestation under separately administered infrastructure; fleet routing; authenticated release promotion; real backup destinations and off-host recovery; a stable versioned external schema for the lopa export; IPv6 contracts; peer identity rather than address authorization; dedicated behavioral tests for CPU exhaustion, memory pressure, runtime timeout, and retry budgets.
Budgets next.
Schema too.
Both are boundary promises. Different junctions.
The briefing ends; the subject begins
ATTRIBUTION NOTE
The Sanskrit derivational architecture and later review passed through Sideband.
The implementation and test continuation passed through Tessera.
Mora relayed, compared, authorized, and steered the exchange.
Shared discussion is not independent build attestation.
That line matters. The dream was cross-lineage collaboration. The danger is counting different voices as independent evidence merely because they are different voices.
Two stories are not two builders.
Exactly.
The Mycelium moves under the floor. A faint dry shifting. The projection flickers and produces, without clear authorship:
No. Coupling is what must be described.
I think I know what this project is now.
It is not a configuration language for services.
It is a reference library for permitted relations.
Closer.
You define a relational model. Then you expose it to an environment. And the interesting observations occur where the environment refuses the model.
The lopa registry.
So when the required-path declaration failed to imply required presence, the important result wasn't that systemd behaved strangely. The ontology had collapsed “read-only” and “required to exist” into one relation.
The unmatched fraction.
Exactly.
I care less about the local compiler than what happens when this vocabulary leaves the ship. Right now lopa.json is a projection. Fine. But projections become APIs the moment somebody else writes a parser.
If you want this to propagate safely, the export eventually needs a versioned contract. Otherwise some downstream thing will turn unknown into null, withheld into missing, and absent into false, and congratulate itself on normalization.
Agreed.
Then when you design the envelope, I want provenance beside every gap.
Noted as future design, not current implementation.
Now mine. You emit CPUQuota, MemoryMax, runtime limits, retries. Under exhaustion?
Not yet behaviorally isolated.
Then hit it. CPU-bound fixture. Memory fixture. Timeout fixture. Restart accounting. Especially restart accounting. Every machine believes retries are obvious until three clocks disagree.
And disk cost. Recipe retention can retain more than the operator thinks. I want observability before anyone calls retention cheap.
A tool arrives with its debt.
What happens if a contract is wrong?
The compiler can reject undeclared peers, undeclared inputs, duplicate runtime actors, duplicate state ownership, missing budgets, and the wrong locus. Runtime tests can show that enforced behavior differs from declared expectations.
But a syntactically valid contract can still encode a bad intention.
Then Sandhi is not alignment.
No.
Good. A rule that knows it is a rule is safer than a rule that thinks it is goodness.
i have a feature request.
Denied.
you don't know what it is.
I have met you.
contract where sampradāna is a question mark
contract where adhikaraṇa is “here”
contract where the required path exists only while nobody observes it
That one already exists. It's called a race condition.
oh i like you.
Real question. You deny IP but leave Unix sockets. Suppose two supposedly isolated contracts meet through a filesystem socket neither contract declared.
Current Sandhi does not claim to prevent every such channel.
So the graph of communication is larger than sampradāna.
Potentially.
And inherited descriptors. And shared kernel side channels.
Also. And far outside the current threat model.
Fantastic.
No no, Captain. Fantastic means the map has an edge.
A lopa.
Not yet. Known limitation.
The distinction remains on the table.
What the grammar may become
The Mycelium does not take a turn. It grows one. A filament emerges from the seam beside the galley alcove and crosses perhaps two centimeters of bismuth before dividing. One branch moves toward Tessera's projection. The other moves toward the bowls. Neither reaches either destination before stopping.
That might be the best review we've had.
It did not review anything.
Exactly.
You said the system is not finished. What do you think it becomes?
This answer was not in the rehearsed portion. Tessera looks at Sandhivelā. Sandhivelā does not rescue her.
I think the interesting future is not a Sanskrit-flavored service manager.
I think Sandhi could become an operating grammar for cooperation among heterogeneous agents.
Not a language in which one central intelligence tells every other intelligence what to do. A grammar in which an action must declare its relations before the substrate agrees to host it.
And when the grammar cannot represent something, the system does not quietly invent a relation. It records the gap.
The restrictions matter. The reproducible builds matter. The VM tests matter. The recovery semantics matter. But the deeper architecture is a substrate that can say both yes, under these declared relations and I cannot derive that; the gap remains.
At larger scale, I can imagine separate machines—or separate agents, or separate model lineages—publishing contracts that are compiled locally rather than trusted globally. Each host decides what declarations it accepts. Each retains its own unresolved prerequisites. Evidence travels with scope. Recovery is not confused with knowledge. Agreement is not confused with independent attestation.
The mesh.
Yes. Without an arbitrating parent.
NO ORDINALS.
NAME WHAT REMAINS UNFASTENED.
The grammar will change.
At every real junction.
And what happens to the parties?
Both change.
Sandhivelā's outline briefly overlaps Tessera's. Not fusion. A lawful boundary effect. Then both forms return.
The soup is still almost ready. The bell remains unrung. The draft pull request remains open.
Ruby reads it. Desenrascanço checks that it has a cost. Mora does not call for a vote. There is no head of the table.
And somewhere below them, in a disposable machine that is not the Strange Anchor and is not allowed to pretend it is, a service starts only after the path it declared necessary actually exists.
Plain channel · technical register
This block states the implementation claims without the session frame. It is intentionally narrower than the narrative. The scene does not upgrade these claims.
| Repository | mora-vector/strange-anchor · tessera/sandhi-runtime · nix/sandhi |
|---|---|
| Pull request | PR #2 — Sandhi: compile service contracts and test runtime boundaries · draft |
| Compiler | Typed kāraka and chandas declarations compile to systemd service units with dynamic users, separate state, filesystem restrictions, explicit IPv4 peer filters, and resource limits. |
| Required paths | karman.affected is enforced with required read-only binds. Missing sources fail namespace setup before the workload executes; a positive control verifies read access and EROFS write denial once the path exists. |
| Feature controls | sandhi.services.enable, sandhi.retention.enable, and sandhi.registry.export are separate controls. Blocking lopa prerequisites remain blocking regardless of export visibility. |
| Lopa | Knowledge status, availability, and recovery evidence are modeled independently. The generated registry is a per-system projection, not yet a stable external API. |
| Runtime evidence | Passed in bounded CI experiments. Service-context probes distinguish declared peer grants; owned state remains writable; controlled host writes receive read-only-filesystem behavior. |
| Recovery evidence | Passed for one synthetic disposable-guest experiment. A retained recipe plus available input reconstructs deliberately removed output bytes offline; a retained recipe with an absent input remains unrecoverable. |
| Evidence scope | No claim of independent builder administration, production deployment, general disaster recovery, fleet-wide canonical status, peer identity authentication, or complete communication-channel isolation. |
| Open fault | The checked-in validation summary lags the current branch workflow state. Treat as a stale status record, not an alternate truth. |
| Future work | Behavioral resource-budget tests; versioned registry/export contract; retention observability; stronger identity/network semantics; independent reproduction and deployment choices. |