Skip to content

Build the master from the profiles' resumes

POST
/api/master/migration
curl --request POST \
--url http://127.0.0.1:8765/api/master/migration \
--header 'Content-Type: application/json' \
--data '{ "answers": { "mq-59c304ca47a1": "a" } }'

Build the master resume from the profiles’ resumes, with the answers to its questions. Answers 201 when the master was written (status created or revised, written true, master the new revision). With a question still open it answers 200, status needs_answers, and writes nothing. Only profiles without a selection take part; with a master already stored their resumes are merged into it. The master is built from the resumes the profiles hold: the union of their lines, the same line and near-duplicates folded (the newer wording kept). Two versions of a line that state DIFFERENT NUMBERS are asked about (questions: both wordings, and the profile that holds each); nothing is written until every question has an answer (a, b, or both). Each profile’s first selection is its own resume, which is not rewritten, so nothing assessed stays as it was. status: needs_answers (questions are open), ready (GET only: a POST would write it), created | revised | unchanged (written), blocked (GET only: blocked says why, e.g. migration_no_profiles or migration_resume_unreadable). contact_removed lists what the privacy strip left out of a resume by profile, kind and line number, never a value. migration.source_lines says what became of EVERY line of the resumes (a line that is not blank; headings, role lines and each line of a wrapped bullet count): in = kept (in the master) + folded (the master holds it already; folded_by_reason) + left_out (left_out_by_reason), and per resume the lines left out, by reason, a sentence saying why, and their line numbers in the stored resume, never their text. resumes[].education (0.1.11.4): the lines that look like education (a heading that names it, or a degree with a school and a year) and did not become an Education entry, when the master would have none: first, last (line numbers), the section that holds them and a message; a report only. Read it before answering: a line the reader left out is not in the master. file (after a write): where the master went in the resumes folder. Local only: no model call.

Media typeapplication/json
object
actor

Who writes: recorded as written_by. Also the X-GigAI-Actor header. Without either, a write from the Scout UI (a browser page of this server) is the operator’s and any other loopback write is the agent’s.

string
Allowed values: operator agent
answers

{question_id: "a" | "b" | "both"}: one answer per question of GET /api/master/migration.

object
revision

Needed only when a master already exists and this changes it: the revision you read.

integer
Example
{
"answers": {
"mq-59c304ca47a1": "a"
}
}

Success.

Media typeapplication/json
object
schema_version
required
Allowed value: scout-master-migration:1
key
additional properties
any
Example
{
"after": {
"offers": [],
"synced": []
},
"blocked": null,
"contact_removed": null,
"file": {
"beside": null,
"name": "master.md",
"not_imported": false,
"path": "~/Documents/GigAI/resumes/master.md",
"revision": 1,
"state": "current",
"written": true,
"wrote": "master.md"
},
"master": {
"content_sha256": "sha256:...",
"counts": {
"by_kind": {
"bullet": 1,
"other": 0,
"skills": 1,
"summary": 1
},
"by_strength": {
"backed": 0,
"quantified": 1,
"stated": 2
},
"entries": 1,
"ids": 4,
"items": 3,
"skills": 3
},
"parent_revision": "revision_7c1d7b9a-0d58-4f0b-8f27-91f4f6f6a2c3",
"record_id": "record_...",
"revision": 3,
"revision_id": "revision_0b6f2f0e-5a0e-4c58-9a57-2d1b6a0c1e11",
"revisions": 3,
"updated_at": "2026-10-04T10:05:00.000000Z",
"written_by": "operator"
},
"migration": {
"entries": 13,
"exact_duplicates": 4,
"ids_assigned": 78,
"lines_in": 71,
"lines_out": 65,
"near_duplicates": [],
"questions": [
{
"answer": null,
"choices": [
"a",
"b",
"both"
],
"entry": "Lumenfold",
"kind": "number_conflict",
"options": [
{
"key": "a",
"profiles": [
"Staff AI Engineer"
],
"text": "Scaled the event pipeline to 2.1 million events a day for 140 internal teams."
},
{
"key": "b",
"profiles": [
"Staff Software Engineer"
],
"text": "Scaled the event pipeline to 1.4 million events a day for 90 internal teams."
}
],
"question": "One line of Experience / Lumenfold is worded twice, with different numbers. Which is right: a, b, or both (keep the two lines)?",
"question_id": "mq-59c304ca47a1",
"section": "experience"
}
],
"resumes": 2,
"source_lines": {
"folded": 17,
"folded_by_reason": {
"conflict": 1,
"exact_duplicate": 4,
"near_duplicate": 2,
"role_line": 3,
"same_entry": 6,
"skills_joined": 1
},
"in": 131,
"kept": 112,
"left_out": 2,
"left_out_by_reason": {
"above_first_section": 2,
"contact": 0,
"empty_section": 0,
"title_heading": 0,
"unknown_section": 0,
"unread": 0
},
"resumes": [
{
"in": 61,
"left_out": [
{
"lines": [
1,
3
],
"reason": "above_first_section",
"why": "above the first section and not a summary paragraph (a name, a title or a headline)"
}
],
"profiles": [
"Staff AI Engineer"
]
},
{
"in": 70,
"left_out": [],
"profiles": [
"Staff Software Engineer"
]
}
]
},
"unanswered": [
"mq-59c304ca47a1"
]
},
"mode": "migration",
"ok": true,
"profiles": [
{
"label": "Staff AI Engineer",
"profile_id": "prof_1",
"resume_ref": {
"content_sha256": "sha256:...",
"record_id": "record_...",
"revision_id": "revision_..."
},
"shown": null,
"skills": null
}
],
"questions": [],
"schema_version": "scout-master-migration:1",
"status": "created",
"written": true
}

Forbidden / forbidden_origin: loopback peer and Host 127.0.0.1:<port> or localhost:<port> only (Origin too on writes).

Media typeapplication/json
object
error
required
object
allowed_keys
Array<string>
code
required
string
message
required
string
key
additional properties
any
Examplegenerated
{
"error": {
"allowed_keys": [
"example"
],
"code": "example",
"message": "example"
}
}

Target_unavailable

Media typeapplication/json
object
error
required
object
allowed_keys
Array<string>
code
required
string
message
required
string
key
additional properties
any
Example
{
"error": {
"code": "target_unavailable",
"message": "..."
}
}

Migration_no_profiles, migration_resume_unreadable, master_exists, revision_conflict

Media typeapplication/json
object
error
required
object
allowed_keys
Array<string>
code
required
string
message
required
string
key
additional properties
any
Example
{
"error": {
"code": "migration_no_profiles",
"message": "..."
}
}

Unsupported_media_type: writes need Content-Type: application/json.

Media typeapplication/json
object
error
required
object
allowed_keys
Array<string>
code
required
string
message
required
string
key
additional properties
any
Examplegenerated
{
"error": {
"allowed_keys": [
"example"
],
"code": "example",
"message": "example"
}
}

Unknown_key, wrong_type, invalid_value, migration_answer_invalid, migration_answer_unknown

Media typeapplication/json
object
error
required
object
allowed_keys
Array<string>
code
required
string
message
required
string
key
additional properties
any
Example
{
"error": {
"code": "unknown_key",
"message": "..."
}
}