continuity.plan
Whether and how a published handover can be resumed here
What it is
Writes nothing. Chooses the record (named, or the one other device's handover this checkout has not resumed, on this branch first) and decides: is its signer trusted, does it diverge from the record this checkout stands on, does the local source hold the commit and branch it was written against, was it written in a dirty tree whose uncommitted files never reached a commit, may the other device still be working. The verdict is ready, ready_with_warnings, requires_source_update, conflict, choose_record, nothing_to_resume or refused, with blockers, warnings, the commands that resolve them (recommended, never run), what a resume restores and what this checkout recomputes for itself.
Descriptor
- Canonical id
continuity.plan- Module
continuity- Kind
- query
- Stability
- experimental
- Provenance
- declared
- Source
apps/majordomus-cli/src/capability/builtin/continuity.rs- Cache
disabled- Benchmark
required- Tags
- continuityhandoverdevices
Run
queryProjections
| Interface | As | Where |
|---|---|---|
| MCP tool | majordomus_continuity_plan | - |
| MCP resource | not exposed | - |
| HTTP | GET /api/v1/continuity/plan | Swagger |
| Command line | majordomus continuity plan | - |
Schemas
Input · RecordInput
{
"type": "object",
"additionalProperties": false,
"properties": {
"record": {
"type": [
"string",
"null"
],
"description": "A record id, or a unique prefix of one."
}
},
"description": "The input of `continuity.plan` and `continuity.resume`: which record, by id or a prefix\nof one. Absent, the one handover another device published that this checkout has not\nresumed — on this branch when there is one there.",
"title": "RecordInput"
}Output · ResumePlan
{
"type": "object",
"properties": {
"status": {
"$ref": "#/$defs/PlanStatus",
"description": "The verdict."
},
"record": {
"anyOf": [
{
"$ref": "#/$defs/RecordView"
},
{
"type": "null"
}
],
"description": "The record it is about."
},
"candidates": {
"type": "array",
"items": {
"$ref": "#/$defs/RecordView"
},
"description": "When the record is not decided: the records that could be meant."
},
"source": {
"anyOf": [
{
"$ref": "#/$defs/SourceCheck"
},
{
"type": "null"
}
],
"description": "The source check."
},
"lineage": {
"anyOf": [
{
"$ref": "#/$defs/Relation"
},
{
"type": "null"
}
],
"description": "What the record is to the record this checkout stands on, when it stands on one."
},
"task": {
"anyOf": [
{
"$ref": "#/$defs/TaskRef"
},
{
"type": "null"
}
],
"description": "The task, as published: the intent."
},
"milestone": {
"type": [
"string",
"null"
],
"description": "The milestone."
},
"decisions": {
"type": "array",
"items": {
"type": "string"
},
"description": "The headings of the decisions a resume carries."
},
"objective": {
"type": "string",
"description": "The handover's `# Objective`."
},
"current_state": {
"type": "string",
"description": "The handover's `# Current State`."
},
"next_action": {
"type": "string",
"description": "The handover's `# Next Action`."
},
"blockers": {
"type": "array",
"items": {
"$ref": "#/$defs/PlanItem"
},
"description": "What stops a resume."
},
"warnings": {
"type": "array",
"items": {
"$ref": "#/$defs/PlanItem"
},
"description": "What a resume proceeds past and a person should know."
},
"actions": {
"type": "array",
"items": {
"type": "string"
},
"description": "The commands that resolve the blockers or follow the resume. Recommended, never run:\nnothing a record says is executed."
},
"restores": {
"type": "array",
"items": {
"$ref": "#/$defs/Component"
},
"description": "What a resume writes into this checkout."
},
"recomputes": {
"type": "array",
"items": {
"$ref": "#/$defs/Component"
},
"description": "What this checkout computes for itself instead of copying."
}
},
"required": [
"status",
"blockers",
"warnings",
"actions",
"restores",
"recomputes"
],
"description": "The answer of `continuity plan`, and the plan `continuity resume` acts on.",
"title": "ResumePlan",
"$defs": {
"PlanStatus": {
"oneOf": [
{
"type": "string",
"const": "ready",
"description": "Resume restores everything; nothing needs attention."
},
{
"type": "string",
"const": "ready_with_warnings",
"description": "Resume restores everything; the warnings say what is not what it was at the origin."
},
{
"type": "string",
"const": "requires_source_update",
"description": "The local source does not hold what the record was written against: update git\nfirst, as the actions say."
},
{
"type": "string",
"const": "conflict",
"description": "The same work was continued twice, or the source histories diverged: a person\nchooses."
},
{
"type": "string",
"const": "choose_record",
"description": "More than one record could be meant: name one with `--record`."
},
{
"type": "string",
"const": "nothing_to_resume",
"description": "Nothing to resume."
},
{
"type": "string",
"const": "refused",
"description": "The record is not one this checkout may resume from (an untrusted signer)."
}
],
"description": "The verdict of a resume plan."
},
"RecordView": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The record id."
},
"line": {
"type": "string",
"description": "Its line."
},
"parent": {
"type": [
"string",
"null"
],
"description": "The record it continues."
},
"device": {
"$ref": "#/$defs/Device",
"description": "The device that published it."
},
"this_device": {
"type": "boolean",
"description": "Whether that device is this one."
},
"trust": {
"$ref": "#/$defs/Trust",
"description": "Whether its signer is trusted here."
},
"session": {
"type": [
"string",
"null"
],
"description": "The episode it was published from."
},
"branch": {
"type": [
"string",
"null"
],
"description": "The branch it was written on."
},
"head": {
"type": [
"string",
"null"
],
"description": "The commit it was written at."
},
"working_tree": {
"$ref": "#/$defs/WorkingTree",
"description": "Clean or dirty at the origin."
},
"changed_total": {
"type": "integer",
"format": "uint",
"minimum": 0,
"description": "How many paths differed from HEAD at the origin."
},
"published_at": {
"type": "string",
"description": "When it was published, by the publisher's clock."
},
"age_minutes": {
"type": [
"integer",
"null"
],
"format": "int64",
"description": "Minutes since then, by this machine's clock; absent when either clock's reading is\nunusable."
},
"task": {
"type": [
"string",
"null"
],
"description": "The task's title: the intent."
},
"issue": {
"type": [
"string",
"null"
],
"description": "The issue."
},
"objective": {
"type": "string",
"description": "The handover's `# Objective`, first line."
}
},
"required": [
"id",
"line",
"device",
"this_device",
"trust",
"working_tree",
"changed_total",
"published_at"
],
"description": "One record as every surface shows it."
},
"Device": {
"type": "object",
"properties": {
"node": {
"type": "string",
"description": "The node id: the first 32 hex of the SHA-256 of the device's Ed25519 public key."
},
"label": {
"type": "string",
"description": "The display label of the device's identity file (`macbook-pro`), or the first eight\nhex of its node id when it has none."
}
},
"required": [
"node",
"label"
],
"description": "The device a record was written on: the mesh node key's id and the label its identity\nfile carries. The label is presentation; the node id is identity."
},
"Trust": {
"oneOf": [
{
"type": "string",
"const": "this_device",
"description": "This device signed it."
},
{
"type": "string",
"const": "trusted",
"description": "The mesh declaration's trust list admits the key."
},
{
"type": "string",
"const": "untrusted",
"description": "The mesh declaration exists and does not admit the key: never resumed from."
},
{
"type": "string",
"const": "undeclared",
"description": "The repository declares no mesh, so no list exists to check the key against. The\nsignature still binds the record to its key; the plan warns."
}
],
"description": "Whether the device that signed a record is one this repository trusts."
},
"WorkingTree": {
"oneOf": [
{
"type": "string",
"const": "clean",
"description": "Nothing outside HEAD."
},
{
"type": "string",
"const": "dirty",
"description": "Modified, staged or untracked files that HEAD does not hold."
}
],
"description": "Whether the working tree had changes git does not hold in a commit."
},
"SourceCheck": {
"type": "object",
"properties": {
"expected_branch": {
"type": [
"string",
"null"
],
"description": "The branch the record was written on."
},
"expected_head": {
"type": [
"string",
"null"
],
"description": "The commit it was written at."
},
"local_branch": {
"type": [
"string",
"null"
],
"description": "This checkout's branch."
},
"local_head": {
"type": [
"string",
"null"
],
"description": "This checkout's commit."
},
"relation": {
"$ref": "#/$defs/SourceRelation",
"description": "How they stand."
},
"origin_dirty": {
"type": "boolean",
"description": "Whether the origin's tree was dirty."
},
"origin_changed": {
"type": "array",
"items": {
"type": "string"
},
"description": "The paths that were uncommitted at the origin, as listed."
},
"origin_changed_total": {
"type": "integer",
"format": "uint",
"minimum": 0,
"description": "How many were uncommitted."
},
"local_dirty": {
"type": "boolean",
"description": "Whether this checkout's tree is dirty."
},
"same_uncommitted_work": {
"type": [
"boolean",
"null"
],
"description": "Whether this checkout holds the very uncommitted work the origin held (their\nfingerprints agree); absent when either side is clean."
}
},
"required": [
"relation",
"origin_dirty",
"origin_changed_total",
"local_dirty"
],
"description": "The source half of a plan."
},
"SourceRelation": {
"oneOf": [
{
"type": "string",
"const": "exact",
"description": "Same branch, same commit."
},
{
"type": "string",
"const": "local_ahead",
"description": "Same branch; the local branch has commits the record did not see."
},
{
"type": "string",
"const": "local_behind",
"description": "Same branch; the record's commit is ahead of the local one."
},
{
"type": "string",
"const": "diverged",
"description": "Same branch; neither commit contains the other."
},
{
"type": "string",
"const": "head_missing",
"description": "The record's commit is not in this clone."
},
{
"type": "string",
"const": "branch_differs",
"description": "This checkout is on another branch."
},
{
"type": "string",
"const": "unknown",
"description": "The record carries no commit, or git could not answer."
}
],
"description": "How the local source stands towards the record's."
},
"Relation": {
"oneOf": [
{
"type": "string",
"const": "equal",
"description": "The same record."
},
{
"type": "string",
"const": "newer",
"description": "The second descends from the first: the second is newer."
},
{
"type": "string",
"const": "older",
"description": "The first descends from the second: the second is older."
},
{
"type": "string",
"const": "diverged",
"description": "Same line, neither descends from the other: the work was continued twice."
},
{
"type": "string",
"const": "independent",
"description": "Different lines: separate work."
}
],
"description": "What one record is to another."
},
"TaskRef": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The task id, `t-<stamp>-<hex>`."
},
"title": {
"type": "string",
"description": "What the task is, in its author's words: the intent."
},
"profile": {
"type": [
"string",
"null"
],
"description": "The profile it ran under."
},
"scope": {
"type": "array",
"items": {
"type": "string"
},
"description": "The repository paths it may touch."
},
"outcome": {
"type": [
"string",
"null"
],
"description": "The outcome the task record held when the handover was published."
}
},
"required": [
"id",
"title"
],
"description": "The task the handover was written under, as the task record named it."
},
"PlanItem": {
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "A stable code: `source_incomplete`, `line_diverged`, `origin_untrusted`, …"
},
"message": {
"type": "string",
"description": "What it means here."
}
},
"required": [
"code",
"message"
],
"description": "One thing a plan says about itself."
},
"Component": {
"oneOf": [
{
"type": "string",
"const": "handover",
"description": "The handover, into this checkout's handovers."
},
{
"type": "string",
"const": "intent",
"description": "The task's title and scope, offered as the `start` to run."
},
{
"type": "string",
"const": "issue",
"description": "The issue and milestone."
},
{
"type": "string",
"const": "decisions",
"description": "The decisions the task recorded, into this checkout's decision log."
},
{
"type": "string",
"const": "next_action",
"description": "The handover's next action."
},
{
"type": "string",
"const": "lineage",
"description": "The record this checkout continues: the parent of its next publication."
},
{
"type": "string",
"const": "provenance",
"description": "Who published it, where, when, from which source state."
},
{
"type": "string",
"const": "worktree",
"description": "This checkout's path, recomputed rather than copied."
},
{
"type": "string",
"const": "repository_id",
"description": "The repository id the shell compares, recomputed."
},
{
"type": "string",
"const": "episode",
"description": "The episode, opened here by the provider's hooks."
},
{
"type": "string",
"const": "working_context",
"description": "The working context, compiled here from the restored records and this git."
},
{
"type": "string",
"const": "source_state",
"description": "The source state, from this checkout's git."
}
],
"description": "What a resume writes, recomputes or leaves."
}
}
}Examples
These are the capability's own benchmark cases: the same inputs the benchmark runs and the OpenAPI document shows.
default
{}by-prefix
{
"record": "0000"
}