Skip to content

HTTP API: layout

The boundary between the layer's tracked and local halves, checked against the layouts their contracts declare: what lives where, and what must never appear there (I1102).

Rendered from docs/generated/openapi.json, which the executable generates from its capability registry and CI refuses stale. The raw document is at /openapi.json; a running server serves the same document at its own /openapi.json and Swagger UI at /swagger.

layout

The boundary between the layer's tracked and local halves, checked against the layouts their contracts declare: what lives where, and what must never appear there (I1102).

GET /api/v1/layout/check layout.check

Refuse a misplaced artifact

Every path a declared layout excludes, named with the contract it violates: a tracked file under the tracked half that git's ignore rules match (state that does not travel, under a contract that excludes cache or runtime), and a file under the local half that is a byte copy of a tracked canonical file or declares the schema of a kind share/kinds.yaml calls canonical (under the manifest's `local.excludes: [canonical]`). Only what a contract declares is judged. Reads git and the local half's files; no build and no network.

  • query
  • behaviorally_verified
  • benchmark required
  • cache disabled
  • MCP tool majordomus_layout_check
  • $ layout check

No parameters.

Try it

The port is whatever the server logged; 8741 is the one it asks for first. The values are the operation's first example.

curl -s "http://127.0.0.1:8741/api/v1/layout/check"

Tested by apps/majordomus-cli/tests/http_serve.rs, which replays the route with these values against a server on a real socket.

Responses

statusbodymeaning
200 LayoutReport
Refuse a misplaced artifact: the result.
400 ErrorBody
invalid_input: The input does not fit the schema: a parameter of the wrong type, an unknown one, or a value the capability rejects.
404 ErrorBody
not_found: The input names something the repository does not hold.
500 ErrorBody
internal: The capability failed for a reason of its own; the message names it.
default ErrorBody
Any other failure the transport reports: 405 method_not_allowed for another method on this path, 400 invalid_input for a body that is not a JSON object.

Schemas

The components only this tag's operations use. Each row is the type's own field, its doc comment the description; a type another page owns links there.

LayoutFinding

object
One misplaced artifact: a path found in a half whose declared layout excludes it, with the contract that excludes it and why, so a refusal names what to move and where it belongs.

It travels as the JSON of the layout.check capability, so its member names are the wire contract every projection reads:

use majordomus_cli::layout::LayoutFinding;
let finding = LayoutFinding {
    path: ".ai/local/notes/rule.md".into(),
    contract: "manifest local".into(),
    excludes: "canonical".into(),
    reason: "a copy of .ai/repo/rules/rule.md".into(),
};
let json = serde_json::to_value(&finding).unwrap();
assert_eq!(json["contract"], "manifest local");
assert_eq!(json["excludes"], "canonical");
let back: LayoutFinding = serde_json::from_value(json).unwrap();
assert_eq!(back, finding);
propertytyperequireddescription
path string yes
The path, repository-relative.
contract string yes
The contract it violates: a context document's id, or manifest local.
excludes string yes
What the contract excludes that this path is.
reason string yes
What the path was found to be, and how.

Used by LayoutReport

LayoutReport

object
The answer of the layout check: whether the halves were read, how many paths were judged, and every path a contract excludes. A report that could not read the halves never passes, so silence about a tree nobody measured cannot read as a clean tree.

use majordomus_cli::layout::LayoutReport;
let clean = LayoutReport::of(true, None, 12, Vec::new());
assert!(clean.passes);
assert_eq!(clean.checked, 12);
let unread = LayoutReport::of(false, Some("git could not start".into()), 0, Vec::new());
assert!(!unread.passes, "nothing found because nothing was read");
assert_eq!(unread.reason.as_deref(), Some("git could not start"));
propertytyperequireddescription
measured boolean yes
Whether the halves could be read at all. false is not a pass.
reason string | null no
Why they could not, when they could not.
checked integer (uint) yes
How many paths were judged.
findings array of LayoutFinding → LayoutFinding yes
Every path a contract excludes, in canonical order. Empty is the passing answer.
passes boolean yes
true when the halves were read and nothing was found.

Used by layout.check

Searches the titles and descriptions of every page this site publishes.