Skip to content

HTTP API: why

The operational failure modes this tool is a response to: the moments a reader recognises, the audiences that recognise them, the areas they fall under, and what a reader's own symptoms imply. Every entry is a file under the layer's why section; nothing here holds a list, and a moment added there is answered by all of these without a registration anywhere.

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.

why

The operational failure modes this tool is a response to: the moments a reader recognises, the audiences that recognise them, the areas they fall under, and what a reader's own symptoms imply. Every entry is a file under the layer's why section; nothing here holds a list, and a moment added there is answered by all of these without a registration anywhere.

GET /api/v1/why why.list

The catalogue

Every operational moment this repository holds, narrowed by any of the facets the catalogue itself reports, with the audiences, the areas, the derived filters and the counts. The default is the public catalogue; pass status=any for the drafts too.

  • query
  • behaviorally_verified
  • benchmark required
  • cache process (max_entries=32)
  • MCP tool majordomus_why
  • MCP resource {"name": "why", "uri": "majordomus://why"}
  • $ why list

Query parameters

nametyperequireddescriptionexamples
audience string no Only moments this audience recognises. by-audience: "agency"
area string no Only moments in this operational area.
tag string no Only moments carrying this tag.
severity string no Only moments of this severity.
frequency string no Only moments of this frequency.
lifecycle string no Only moments at this stage of work.
capability string no Only moments naming this capability of the executable.
command string no Only moments naming this command.
featured boolean no Only moments the homepage features.
status string no Only moments of this status. Absent means the public ones (`stable`); pass `any` for everything the catalogue holds.
q string no Case-insensitive text, matched against the identity, the titles, the hook, the summary, the tags, the aliases, the signals, the examples and the body. search: "context"

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/why?audience=agency&q=context"

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 CatalogueView The catalogue: 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.
GET /api/v1/why/areas why.areas

Operational areas

Every operational area the catalogue declares, each with the public moments that fall under it. Membership is derived from the moments and is never listed in an area's own file.

  • query
  • behaviorally_verified
  • benchmark required
  • cache process (max_entries=4)
  • MCP tool majordomus_why_areas
  • MCP resource {"name": "why-areas", "uri": "majordomus://why/areas"}
  • $ why areas

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/why/areas"

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 AreaList Operational areas: 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.
GET /api/v1/why/audiences why.audiences

Audiences

Every audience the catalogue declares, each with the public moments that name it. Membership is derived from the moments and is never listed in an audience's own file.

  • query
  • behaviorally_verified
  • benchmark required
  • cache process (max_entries=4)
  • MCP tool majordomus_why_audiences
  • MCP resource {"name": "why-audiences", "uri": "majordomus://why/audiences"}
  • $ why audiences

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/why/audiences"

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 AudienceList Audiences: 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.
GET /api/v1/why/diagnose why.diagnose

Diagnose a selection

What a reader's own symptoms imply: the moments the selection resolves to, the operational areas and audiences they weigh towards, and the capabilities, commands, claims, rules and use cases that answer them — each carrying the moments that produced it. Counting, not inference: there is no weighting and no percentage.

  • query
  • behaviorally_verified
  • benchmark required
  • cache process (max_entries=32)
  • MCP tool majordomus_why_diagnose
  • $ why diagnose

Query parameters

nametyperequireddescriptionexamples
signals string no Signal ids or moment ids, separated by commas. Empty selects nothing and is answered with an empty diagnosis rather than an error. three-moments: "abandoned-worktree,api-changed-contract-did-not,code-without-an-issue"

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/why/diagnose?signals=abandoned-worktree%2Capi-changed-contract-did-not%2Ccode-without-an-issue"

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 Diagnosis Diagnose a selection: 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.
GET /api/v1/why/moment why.moment

One moment

One operational moment in full: what it looks like, why it happens, what it costs, what this tool does about it, and every relation derived from its metadata — the responsibilities its claims belong to, the moments that name it, and the moments nearest it by shared area, audience and tag.

  • query
  • behaviorally_verified
  • benchmark required
  • cache process (max_entries=64)
  • MCP tool majordomus_why_moment
  • $ why show

Query parameters

nametyperequireddescriptionexamples
id string yes The moment's id, as `why.list` gives it. This is also its slug and its route. first-moment: "abandoned-worktree"

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/why/moment?id=abandoned-worktree"

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 MomentDetail One moment: 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.
GET /api/v1/why/validate why.validate

Validate the catalogue

Every finding over the catalogue: a reference that resolves to nothing, with the nearest candidate; a duplicate identity; a file name that disagrees with its id; and a public record that does not meet the floor its status promises. Errors make the catalogue invalid; warnings do not.

  • query
  • behaviorally_verified
  • benchmark required
  • cache process (max_entries=2)
  • MCP tool majordomus_why_validate
  • $ why validate

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/why/validate"

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 ValidationReport Validate the catalogue: 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.

AreaList

object
Every area.
propertytyperequireddescription
count integer (uint) yes How many.
areas array of AreaView → AreaView yes Each, with its derived membership, in presentation order.

Used by why.areas

AreaView

object
One area, with the membership nobody authored.
propertytyperequireddescription
id string yes The identity, the slug and the file name.
title string yes The area.
summary string yes One line: what falls under it.
status string yes stable, draft or deprecated.
weight integer (uint32) no Presentation order.
tags array of string no Free tags.
route string no Derived: /why/areas/<id>/.
source string no Derived: the file it came from.
body string no The Markdown body.
moments array of string yes Derived: the public moments that fall under it, in presentation order.
count integer (uint) yes Derived: how many.

Used by AreaList CatalogueView

AudienceList

object
Every audience.
propertytyperequireddescription
count integer (uint) yes How many.
audiences array of AudienceView → AudienceView yes Each, with its derived membership, in presentation order.

Used by why.audiences

AudienceView

object
One audience, with the membership nobody authored.
propertytyperequireddescription
id string yes The identity, the slug and the file name.
title string yes Who they are.
short_title string | null no Two or three words for a filter chip.
summary string yes One line: the working situation.
workflow string | null no One line: how work flows for them.
status string yes stable, draft or deprecated.
weight integer (uint32) no Presentation order.
tags array of string no Free tags.
route string no Derived: /why/audiences/<id>/.
source string no Derived: the file it came from.
body string no The Markdown body.
moments array of string yes Derived: the public moments that name it, in presentation order.
count integer (uint) yes Derived: how many.

Used by AudienceList CatalogueView

CatalogueView

object
The whole catalogue as a client reads it.
propertytyperequireddescription
schema string yes SCHEMA.
fingerprint string yes The hash of the catalogue's own sources: stable for a tree, and independent of the rest of the index, so two runs over one tree agree.
counts Counts → Counts yes The counts.
moments array of MomentSummary → MomentSummary yes The matching moments, in presentation order.
audiences array of AudienceView → AudienceView yes Every audience, with its derived membership.
areas array of AreaView → AreaView yes Every area, with its derived membership.
facets Facets → Facets yes The filters, derived from the records.

Used by why.list

Counts

object
How much the catalogue holds. Every count anywhere — a page, a heading, a report — is one of these, so no number is ever written down.
propertytyperequireddescription
moments integer (uint) yes Public moments.
moments_all integer (uint) yes Moments of every status, drafts included.
audiences integer (uint) yes Public audiences.
areas integer (uint) yes Public areas.
signals integer (uint) yes Signals across the public moments: the size of the questionnaire.
examples integer (uint) yes Concrete situations across the public moments.

Used by CatalogueView ValidationReport

Diagnosis

object
What a reader's selection implies, computed by counting rather than by inference.

The arithmetic is the whole model and is stated so a reader can check it: a selection resolves to a set of moments; an area or an audience scores the number of selected moments that name it; a recommendation scores the number that name it and carries their ids. There is no weighting and no percentage, because there is no model behind one.

propertytyperequireddescription
moments array of string yes The moments the selection resolved to, in presentation order.
unresolved array of string yes Selected names that resolved to nothing.
areas array of Recommendation → Recommendation yes Operational areas by how many selected moments fall under them, heaviest first.
audiences array of Recommendation → Recommendation yes Audiences by how many selected moments they recognise, heaviest first.
capabilities array of Recommendation → Recommendation yes Capabilities of the executable that answer the selected moments.
commands array of Recommendation → Recommendation yes Commands that answer them.
claims array of Recommendation → Recommendation yes Claims that say what is guaranteed.
doctrines array of Recommendation → Recommendation yes Rules of the effective set that govern them.
use_cases array of Recommendation → Recommendation yes Use cases that show the way out.
also_worth_reading array of string yes Moments the selection did not include that share an area with one that it did.

Used by why.diagnose

Example

object
One concrete situation, in one audience, with what happens today and what happens instead.
propertytyperequireddescription
id string yes Unique within the moment.
audience string yes The audience this situation belongs to; must name an audience of the catalogue.
title string yes One line naming the situation.
before string yes What happens without the tool.
after string yes What happens with it.

Used by MomentDetail

FacetValue

object
One selectable value of one facet, with how many public moments carry it. Every filter a reader is offered is one of these; nothing anywhere lists the values by hand.
propertytyperequireddescription
value string yes The value as a moment declares it.
label string yes The name to show; the value itself when the taxonomy holds no title for it.
count integer (uint) yes How many public moments carry it.

Used by Facets

Facets

object
The filters the catalogue offers, derived from the records rather than declared.
propertytyperequireddescription
audiences array of FacetValue → FacetValue yes By audience.
areas array of FacetValue → FacetValue yes By operational area.
tags array of FacetValue → FacetValue yes By tag.
severities array of FacetValue → FacetValue yes By severity.
frequencies array of FacetValue → FacetValue yes By frequency.
lifecycle array of FacetValue → FacetValue yes By stage of work.
capabilities array of FacetValue → FacetValue yes By capability of the executable.
commands array of FacetValue → FacetValue yes By command.

Used by CatalogueView

Finding

object
One thing wrong with the catalogue, named where it is, with the nearest candidate when there is one. A finding always carries enough to fix it without searching.
propertytyperequireddescription
severity Severity → Severity yes error or warning.
code string yes A short category: unknown_reference, duplicate_identity, missing_content, ...
path string yes The repository-relative file the finding is in.
id string | null no The record's identity, when one record owns the finding.
field string | null no The front-matter key the finding is about, when one key owns it.
message string yes What is wrong, in one sentence.
did_you_mean string | null no The nearest existing name, when the value looks like a typo of one.

Used by ValidationReport

MomentDetail

object
One moment in full, with everything derived that a page shows and no file states.
propertytyperequireddescription
id string yes The identity, the slug and the file name.
title string yes The moment as a heading.
short_title string | null no Two or three words for a narrow column, when the record carries one.
hook string yes The first-person line an index shows.
summary string yes One line: what is actually wrong.
status string yes stable, draft or deprecated.
severity string yes low, medium or high.
frequency string yes rare, occasional, common or constant.
weight integer (uint32) no Presentation order, lowest first.
featured boolean no Whether the homepage shows it.
audiences array of string yes The audiences that recognise it.
areas array of string yes The operational areas it falls under.
lifecycle array of string no The stages of work at which it shows up.
tags array of string no Free tags.
signals array of Signal → Signal yes The observable symptoms.
examples array of Example → Example yes The concrete situations.
commands array of string no Commands of the tool that answer it.
capabilities array of string no Capability ids of the executable that answer it.
claims array of string no Claims that say what is guaranteed here.
doctrines array of string no Rules of the effective set that govern it.
use_cases array of string no Use cases that show the way out.
related array of string no Moments explicitly related to this one. The reverse is derived.
aliases array of string no Other words a reader might search for.
route string no Derived: /why/<id>/. Never authored; the schema refuses a route key.
source string no Derived: the repository-relative file the record came from.
body string no The Markdown body, without its front matter.
responsibilities array of string yes Derived: the responsibilities the claims it names belong to.
backlinks array of string yes Derived: the moments that name this one in their related.
similar array of string yes Derived: moments sharing an area or an audience with this one and not already named by it, nearest first — most shared metadata, then presentation order.
related_detail array of MomentSummary → MomentSummary yes Derived: the explicitly related moments, summarised so a page needs one call.
neighbours array of string yes Derived: what a reader should see next, in one list and in a stated order — what this moment names, then what names it, then what is nearest by shared metadata, each appearing once. The three lists above are the same relations kept apart for a reader that wants to know which is which.

Used by why.moment

MomentSummary

object
One moment as a listing shows it: everything a card needs and nothing a page needs.
propertytyperequireddescription
id string yes The identity and the slug.
title string yes The moment as a heading.
label string yes The name a narrow column shows: the short title, or the title.
hook string yes The first-person line an index shows.
summary string yes One line: what is actually wrong.
status string yes stable, draft or deprecated.
severity string yes low, medium or high.
frequency string yes rare, occasional, common or constant.
weight integer (uint32) yes Presentation order.
featured boolean yes Whether the homepage shows it.
audiences array of string yes The audiences that recognise it.
areas array of string yes The operational areas it falls under.
tags array of string yes Free tags.
route string yes Derived: /why/<id>/.
signals integer (uint) yes How many observable symptoms it declares.
examples integer (uint) yes How many concrete situations it carries.

Used by CatalogueView MomentDetail

Recommendation

object
One recommendation, with the moments that produced it. A recommendation with no matched_because is a recommendation nobody can check.
propertytyperequireddescription
id string yes The thing recommended: a capability id, a command, a claim, a rule, a use case.
count integer (uint) yes How many of the selected moments name it.
matched_because array of string yes The selected moments that named it, in presentation order.

Used by Diagnosis

Signal

object
One observable symptom of a moment: a question a reader can answer about their own week. The questionnaire on the site and the input of why diagnose are these and nothing else.
propertytyperequireddescription
id string yes Unique within the moment; the identity a diagnosis selects by.
text string yes The symptom, phrased so a reader can say whether it happened to them.

Used by MomentDetail

ValidationReport

object
What the catalogue's own validation found.
propertytyperequireddescription
valid boolean yes True when nothing is an error. Warnings do not make it false.
errors integer (uint) yes How many findings are errors: a reference that resolves to nothing, a duplicate identity, a file name that disagrees with its id.
warnings integer (uint) yes How many findings are warnings: a public record that does not meet its floor.
counts Counts → Counts yes The counts the catalogue reached.
findings array of Finding → Finding yes The findings, errors first, then by file.

Used by why.validate

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