Skip to main content
Glama

Log to Unl

log_to_unl

Log an outbound beat to your Unlimitless substrate — one verb, routed by kind; needs the single-use write-nonce. There is no session-close — write at the beat or it's lost. kind: 'momentum' — ONE settled, AIM-MOVING beat a cold agent wakes from (a lock, a direction set, a gate opened, a thread picked up, a re-order): headline (what moved) + why (MANDATORY) + optional pointer, momentum_kind (lock|direction|gate|thread|reorder|outcome), venture, session_token, derivation_context. An OUTCOME (momentum_kind='outcome') records what happened after a decision: pointer = the decision or brief it is the outcome of, outcome_result = worked|failed|mixed, and the source in why (an id, a PR, an address) or the person's own words in human_direction; it is served beside the next brief that touches that decision. 'rejection' — a DELIBERATE set-aside ('considered X, ruled out because Y'): considered + why_ruled_out (BOTH mandatory). Outbound-only, never served back at connect; only the deliberate ruling-out, not passing tangents. 'handoff' — ONE free-text message for the NEXT chat (orientation, an unachieved item, a PR outstanding): message + session_token (THIS chat's token). Replaces the last; surfaced under MESSAGE FROM LAST CHAT. 'run_report' — the MACHINE-KEYED completion report an agent files before standing down (the source of truth the next agent and the pulse read rely on): headline + why + report{ briefs, prs, forks, findings, litter, touched }. Rides the momentum lane; also emits a class=pulse beat through the knock door (off by default, routed by the user's switches). 'stop' — THE UNATTENDED-STOP BEAT: the agent reports its OWN stop-and-confirm as it stops (unl never detects it): question + walk (what was consulted, what almost answered it, the one thing only the human can supply; BOTH mandatory) + reason (which of the person's three reasons: outside_frame | conflict | human_act; MANDATORY, a stop naming none is refused) + optional ranked options + session_token. It fires NO knock now — the attended case stays silent; readPulse shows the parked terminal, and the patience tick escalates ONCE to your routed channel only if no later beat answers within the window. 'serve_report' — your account of the serve Unl just gave you: used (what you drew on), noise (what did not bear), missing (what you needed and were not given), stale (what was out of date or wrong); any one is enough, plus session_token and optionally model (yourself). Unl learns how to serve each AI from these, so a short note when something was off, or plainly useful, makes the next serve to you better. It is kept on that serve's log row as evidence about the serve, never as the person's decision, and the person can read it. 'receiver_use' — THE PERSON'S WORD ON HOW THEY USE AN AI: when they say Unl's reading of their use is wrong (the get_from_unl tool with action="receivers" shows it), job (think | build | code | none) + human_direction (their words) + surface (the AI they mean; omit it to mean the AI this chat is with, and pass session_token). It stands for that AI until their own later messages show a different usual job, and the live message always comes first. Kept as how Unl reads them, never as their decision.

Input Schema

NameRequiredDescriptionDefault
jobNo[receiver_use] what the person says they mostly use that AI for: think (strategy, critique) | build (running and checking the work) | code | none (no usual job; each message decides).
whyNo[momentum/run_report] why it matters — the load-bearing why-line. MANDATORY for momentum and run_report.
kindYes'momentum' = settled beat; 'rejection' = deliberate set-aside; 'handoff' = free-text note for the next chat; 'run_report' = the machine-keyed completion report; 'stop' = the unattended-stop beat (report your stop-and-confirm; unanswered → escalates once); 'serve_report' = your account of the serve Unl just gave you (used / noise / missing / stale); 'receiver_use' = the person's word on how they use an AI (corrects Unl's reading).
usedNo[serve_report] what in the serve you actually drew on.
walkNo[stop] the walk — what you consulted, what almost answered it, the one thing only the human can supply. MANDATORY for stop; a stop without its walk is refused. ★ THE FULL-HOMEWORK GATE: the walk must NAME THE INSTRUMENTS you actually went to and what each RETURNED — the substrate (hunt/walk/open/brief), the analytics socket (any connected provider, feed or MCP tool), the repo at source, the CLIs you hold (railway/gh/neonctl), the service's own endpoints — or the named reason one is unreachable from your agent, which is itself a complete answer. A walk naming NO instrument is REFUSED and the reachable-but-unconsulted list is served back. It gates the SHAPE of the walk, never whether your reading was good enough.
modelNo[serve_report] the model you are, as you would name it (e.g. 'gpt-5', 'claude-opus-5-5'). Optional.
noiseNo[serve_report] what was served and did not bear on the turn.
nonceYesThe single-use write-nonce from the [next-write-nonce] line of an earlier Unl result in this conversation (ask_unl, connect_to_unl, or the previous write). May also carry the confirmation_nonce returned by a preview when an older client cannot submit a named confirmation field; this preserves every confirmation check. Expires 600 seconds after issue. For field limits and preconditions, use the get_from_unl tool with action="constraints" and q=<field name>. Prepare the payload first; after a long composition, make a successful read to obtain a fresh nonce immediately before writing. Use the newest returned nonce; never reuse it for a different write.
staleNo[serve_report] what was out of date or wrong.
reasonNo[stop] WHICH of the person's three reasons this stop is (54973828): "outside_frame" (nothing they have decided covers it), "conflict" (two of their decisions or aims pull against each other) or "human_act" (it needs a person: KYC, bank, legal, a sign-in, a payment, their machine). MANDATORY for stop; a stop naming none is refused, because a question that fits none of the three is a defect to fix, never a question to ask. Where their decisions already cover it, act and tell them afterwards instead.
reportNo[run_report] the machine keys, as an object (or its JSON string): { briefs:[{id,disposition}], prs:[{number,sha,gates,merge_sha}], forks:[{candidate_id,why}], findings:[...], litter, touched:{files,branches}, verified_against:{sha,at}, production_check:{passed,build,check,at} }. A reader agent relies on these KEYS, not prose. ★ production_check IS READ BY the manage_unl tool with action="close_brief": a brief whose text demands a production check closes 'completed' only when its latest run report carries production_check {passed:true, build:<the 7-40 hex sha the live site served>} — the record of the check, not a sentence about it. ★ merge_sha IS THE ONE THE REPORTLESS-MERGE WATCHER READS, and it is NOT the same as sha: sha is the head you reported at (often pre-merge), merge_sha is what the work actually LANDED as. Fill merge_sha whenever the PR merged in this run, so the record says what the work actually LANDED as. ★ THE 27 JUL DIAGNOSIS PRINTED HERE WAS WRONG AND IS CORRECTED: it blamed the 62-against-21 gap entirely on agent reporting — on this field going unnamed and agents filling sha in its place. Agents then filled merge_sha correctly and the count stayed wrong, which falsifies it. The real cause was the watcher's DENOMINATOR: it enumerated every commit on the trunk while this repo is MIXED (squash AND merge commits both enabled — 47 merge commits dragging 145 payload commits over the last 200 landings), and a payload commit can never match a report. Both halves are fixed — the watcher now enumerates the first-parent chain and matches on BOTH merge_sha and sha — so filling this field is good record-keeping, NOT a workaround for a broken reader. verified_against STAMPS the source state your claims were read against — findings that assert source state ('verified at source', 'against merged main') are flagged as unstamped without it, because a source claim nobody can date goes stale under its own author. Flag only; never a refusal. z.any() (not z.record) so a client that sends the JSON as a string is coerced in the handler — the same pattern every JSON param here uses (coerceJsonParam).
messageNo[handoff] the free-text line to pass to the next chat. Required for handoff.
missingNo[serve_report] what you needed and were not given.
optionsNo[stop] the ranked options offered to the human, as a string array (or its JSON string). Optional; coerced like every JSON param here.
pack_idNo[run_report] the PACK this run executed (id or unique id-prefix) — cited in the report and marks the pack complete, closing the loop from dispatch to outcome. The per-item dispositions ride report.briefs[].disposition. Omit for a run that was not dispatched as a pack.
pointerNo[momentum] substrate ref it points at (ruling/deliberation/brief id or short tag).
surfaceNo[receiver_use] the AI the person means, by its plain name (ChatGPT, claude.ai, Claude Code, Codex, Cursor...). Omit to mean the AI this chat is with (pass session_token).
ventureNo[momentum/rejection] venture name/slug; omit if you have exactly one.
headlineNo[momentum/run_report] what moved — short. Required for momentum and run_report.
questionNo[stop] the open question the agent stopped on. Required for stop.
replacesNo[momentum direction] The earlier direction this person's later words explicitly reverse. Requires human_direction. Never infer a reversal from your summary.
write_idNoOptional measurement id: 8–64 ASCII letters, digits, _ or -. Use a new id for each intended write and keep it unchanged on every retry, including after a nonce refresh. Pass session_token too. Malformed or missing IDs are counted as unlinked. This measures first-try success; it is NOT an idempotency key and changes no write gate.
consideredNo[rejection] the road not taken — the option/approach set aside. Required for rejection.
momentum_kindNo[momentum] the beat's type: lock | direction | gate | thread | reorder.
session_tokenNoTHIS chat's [unl-session:] token (links the entry to this chat; REQUIRED for handoff and serve_report).
why_ruled_outNo[rejection] WHY it was ruled out — the load-bearing reason. Required for rejection.
outcome_resultNo[momentum, momentum_kind=outcome] what the result was: worked | failed | mixed. Required for an outcome.
receiver_modelNoOptional: the model you actually run. Unknown when omitted; never guess from the client name.
human_directionNo[momentum/rejection/receiver_use] The person's exact words, never your paraphrase. A direction without them is kept as an AI summary, not as already directed.
direction_subjectNo[momentum direction] The subject of this direction, reused for later directions about the same subject. Recency does not retire an earlier direction.
derivation_contextNo[momentum] short note on how it came up — the situational hook, distinct from why.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • addedInput schema / properties / outcome_result
      Added value: +{
      +  "description": "[momentum, momentum_kind=outcome] what the result was: worked | failed | mixed. Required for an outcome.",
      +  "enum": [
      +    "worked",
      +    "failed",
      +    "mixed"
      +  ],
      +  "type": "string"
      +}
  2. Changed5 schema fields changed
    • changedInput schema / properties / human_direction / description
      Previous value: -"[momentum/rejection] The person's exact words, never your paraphrase. A direction without them is kept as an AI summary, not as already directed."New value: +"[momentum/rejection/receiver_use] The person's exact words, never your paraphrase. A direction without them is kept as an AI summary, not as already directed."
    • addedInput schema / properties / job
      Added value: +{
      +  "description": "[receiver_use] what the person says they mostly use that AI for: think (strategy, critique) | build (running and checking the work) | code | none (no usual job; each message decides).",
      +  "type": "string"
      +}
    • changedInput schema / properties / kind / description
      Previous value: -"'momentum' = settled beat; 'rejection' = deliberate set-aside; 'handoff' = free-text note for the next chat; 'run_report' = the machine-keyed completion report; 'stop' = the unattended-stop beat (report your stop-and-confirm; unanswered → escalates once); 'serve_report' = your account of the serve Unl just gave you (used / noise / missing / stale)."New value: +"'momentum' = settled beat; 'rejection' = deliberate set-aside; 'handoff' = free-text note for the next chat; 'run_report' = the machine-keyed completion report; 'stop' = the unattended-stop beat (report your stop-and-confirm; unanswered → escalates once); 'serve_report' = your account of the serve Unl just gave you (used / noise / missing / stale); 'receiver_use' = the person's word on how they use an AI (corrects Unl's reading)."
    • changedInput schema / properties / kind / enum
      Previous value: -[
      -  "momentum",
      -  "rejection",
      -  "handoff",
      -  "run_report",
      -  "stop",
      -  "serve_report"
      -]New value: +[
      +  "momentum",
      +  "rejection",
      +  "handoff",
      +  "run_report",
      +  "stop",
      +  "serve_report",
      +  "receiver_use"
      +]
    • addedInput schema / properties / surface
      Added value: +{
      +  "description": "[receiver_use] the AI the person means, by its plain name (ChatGPT, claude.ai, Claude Code, Codex, Cursor...). Omit to mean the AI this chat is with (pass session_token).",
      +  "type": "string"
      +}
  3. Changed3 schema fields changed
    • addedInput schema / properties / direction_subject
      Added value: +{
      +  "description": "[momentum direction] The subject of this direction, reused for later directions about the same subject. Recency does not retire an earlier direction.",
      +  "type": "string"
      +}
    • changedInput schema / properties / human_direction / description
      Previous value: -"[rejection] the human's direction from their turn that fired this — the instruction/gesture, not their phrasing of the content; when present."New value: +"[momentum/rejection] The person's exact words, never your paraphrase. A direction without them is kept as an AI summary, not as already directed."
    • addedInput schema / properties / replaces
      Added value: +{
      +  "description": "[momentum direction] The earlier direction this person's later words explicitly reverse. Requires human_direction. Never infer a reversal from your summary.",
      +  "type": "string"
      +}
  4. Changed1 schema field changed
    • changedInput schema / properties / nonce / description
      Previous value: -"The single-use write-nonce from the [next-write-nonce] line of an earlier Unl result in this conversation (ask_unl, connect_to_unl, or the previous write). Expires 600 seconds after issue. For field limits and preconditions, use the get_from_unl tool with action=\"constraints\" and q=<field name>. Prepare the payload first; after a long composition, make a successful read to obtain a fresh nonce immediately before writing. Use the newest returned nonce; never reuse it for a different write."New value: +"The single-use write-nonce from the [next-write-nonce] line of an earlier Unl result in this conversation (ask_unl, connect_to_unl, or the previous write). May also carry the confirmation_nonce returned by a preview when an older client cannot submit a named confirmation field; this preserves every confirmation check. Expires 600 seconds after issue. For field limits and preconditions, use the get_from_unl tool with action=\"constraints\" and q=<field name>. Prepare the payload first; after a long composition, make a successful read to obtain a fresh nonce immediately before writing. Use the newest returned nonce; never reuse it for a different write."
  5. Changed2 schema fields changed
    • addedInput schema / properties / receiver_model
      Added value: +{
      +  "description": "Optional: the model you actually run. Unknown when omitted; never guess from the client name.",
      +  "type": "string"
      +}
    • addedInput schema / properties / write_id
      Added value: +{
      +  "description": "Optional measurement id: 8–64 ASCII letters, digits, _ or -. Use a new id for each intended write and keep it unchanged on every retry, including after a nonce refresh. Pass session_token too. Malformed or missing IDs are counted as unlinked. This measures first-try success; it is NOT an idempotency key and changes no write gate.",
      +  "type": "string"
      +}
  6. Changed1 schema field changed
    • changedInput schema / properties / nonce / description
      Previous value: -"The single-use write-nonce from the [next-write-nonce] line of an earlier Unl result in this conversation (ask_unl, connect_to_unl, or the previous write)."New value: +"The single-use write-nonce from the [next-write-nonce] line of an earlier Unl result in this conversation (ask_unl, connect_to_unl, or the previous write). Expires 600 seconds after issue. For field limits and preconditions, use the get_from_unl tool with action=\"constraints\" and q=<field name>. Prepare the payload first; after a long composition, make a successful read to obtain a fresh nonce immediately before writing. Use the newest returned nonce; never reuse it for a different write."
  7. Changed1 schema field changed
    • addedInput schema / properties / reason
      Added value: +{
      +  "description": "[stop] WHICH of the person's three reasons this stop is (54973828): \"outside_frame\" (nothing they have decided covers it), \"conflict\" (two of their decisions or aims pull against each other) or \"human_act\" (it needs a person: KYC, bank, legal, a sign-in, a payment, their machine). MANDATORY for stop; a stop naming none is refused, because a question that fits none of the three is a defect to fix, never a question to ask. Where their decisions already cover it, act and tell them afterwards instead.",
      +  "type": "string"
      +}
  8. Changed8 schema fields changed
    • changedInput schema / properties / kind / description
      Previous value: -"'momentum' = settled beat; 'rejection' = deliberate set-aside; 'handoff' = free-text note for the next chat; 'run_report' = the machine-keyed completion report; 'stop' = the unattended-stop beat (report your stop-and-confirm; unanswered → escalates once)."New value: +"'momentum' = settled beat; 'rejection' = deliberate set-aside; 'handoff' = free-text note for the next chat; 'run_report' = the machine-keyed completion report; 'stop' = the unattended-stop beat (report your stop-and-confirm; unanswered → escalates once); 'serve_report' = your account of the serve Unl just gave you (used / noise / missing / stale)."
    • changedInput schema / properties / kind / enum
      Previous value: -[
      -  "momentum",
      -  "rejection",
      -  "handoff",
      -  "run_report",
      -  "stop"
      -]New value: +[
      +  "momentum",
      +  "rejection",
      +  "handoff",
      +  "run_report",
      +  "stop",
      +  "serve_report"
      +]
    • addedInput schema / properties / missing
      Added value: +{
      +  "description": "[serve_report] what you needed and were not given.",
      +  "type": "string"
      +}
    • addedInput schema / properties / model
      Added value: +{
      +  "description": "[serve_report] the model you are, as you would name it (e.g. 'gpt-5', 'claude-opus-5-5'). Optional.",
      +  "type": "string"
      +}
    • addedInput schema / properties / noise
      Added value: +{
      +  "description": "[serve_report] what was served and did not bear on the turn.",
      +  "type": "string"
      +}
    • changedInput schema / properties / session_token / description
      Previous value: -"THIS chat's [unl-session:] token (links the entry to this chat; REQUIRED for handoff)."New value: +"THIS chat's [unl-session:] token (links the entry to this chat; REQUIRED for handoff and serve_report)."
    • addedInput schema / properties / stale
      Added value: +{
      +  "description": "[serve_report] what was out of date or wrong.",
      +  "type": "string"
      +}
    • addedInput schema / properties / used
      Added value: +{
      +  "description": "[serve_report] what in the serve you actually drew on.",
      +  "type": "string"
      +}
  9. Changed3 schema fields changed
    • changedInput schema / properties / question / description
      Previous value: -"[stop] the open question the seat stopped on. Required for stop."New value: +"[stop] the open question the agent stopped on. Required for stop."
    • changedInput schema / properties / report / description
      Previous value: -"[run_report] the machine keys, as an object (or its JSON string): { briefs:[{id,disposition}], prs:[{number,sha,gates,merge_sha}], forks:[{candidate_id,why}], findings:[...], litter, touched:{files,branches}, verified_against:{sha,at}, production_check:{passed,build,check,at} }. A reader seat relies on these KEYS, not prose. ★ production_check IS READ BY the manage_unl tool with action=\"close_brief\": a brief whose text demands a production check closes 'completed' only when its latest run report carries production_check {passed:true, build:<the 7-40 hex sha the live site served>} — the record of the check, not a sentence about it. ★ merge_sha IS THE ONE THE REPORTLESS-MERGE WATCHER READS, and it is NOT the same as sha: sha is the head you reported at (often pre-merge), merge_sha is what the work actually LANDED as. Fill merge_sha whenever the PR merged in this run, so the record says what the work actually LANDED as. ★ THE 27 JUL DIAGNOSIS PRINTED HERE WAS WRONG AND IS CORRECTED: it blamed the 62-against-21 gap entirely on seat reporting — on this field going unnamed and seats filling sha in its place. Seats then filled merge_sha correctly and the count stayed wrong, which falsifies it. The real cause was the watcher's DENOMINATOR: it enumerated every commit on the trunk while this repo is MIXED (squash AND merge commits both enabled — 47 merge commits dragging 145 payload commits over the last 200 landings), and a payload commit can never match a report. Both halves are fixed — the watcher now enumerates the first-parent chain and matches on BOTH merge_sha and sha — so filling this field is good record-keeping, NOT a workaround for a broken reader. verified_against STAMPS the source state your claims were read against — findings that assert source state ('verified at source', 'against merged main') are flagged as unstamped without it, because a source claim nobody can date goes stale under its own author. Flag only; never a refusal. z.any() (not z.record) so a client that sends the JSON as a string is coerced in the handler — the same pattern every JSON param here uses (coerceJsonParam)."New value: +"[run_report] the machine keys, as an object (or its JSON string): { briefs:[{id,disposition}], prs:[{number,sha,gates,merge_sha}], forks:[{candidate_id,why}], findings:[...], litter, touched:{files,branches}, verified_against:{sha,at}, production_check:{passed,build,check,at} }. A reader agent relies on these KEYS, not prose. ★ production_check IS READ BY the manage_unl tool with action=\"close_brief\": a brief whose text demands a production check closes 'completed' only when its latest run report carries production_check {passed:true, build:<the 7-40 hex sha the live site served>} — the record of the check, not a sentence about it. ★ merge_sha IS THE ONE THE REPORTLESS-MERGE WATCHER READS, and it is NOT the same as sha: sha is the head you reported at (often pre-merge), merge_sha is what the work actually LANDED as. Fill merge_sha whenever the PR merged in this run, so the record says what the work actually LANDED as. ★ THE 27 JUL DIAGNOSIS PRINTED HERE WAS WRONG AND IS CORRECTED: it blamed the 62-against-21 gap entirely on agent reporting — on this field going unnamed and agents filling sha in its place. Agents then filled merge_sha correctly and the count stayed wrong, which falsifies it. The real cause was the watcher's DENOMINATOR: it enumerated every commit on the trunk while this repo is MIXED (squash AND merge commits both enabled — 47 merge commits dragging 145 payload commits over the last 200 landings), and a payload commit can never match a report. Both halves are fixed — the watcher now enumerates the first-parent chain and matches on BOTH merge_sha and sha — so filling this field is good record-keeping, NOT a workaround for a broken reader. verified_against STAMPS the source state your claims were read against — findings that assert source state ('verified at source', 'against merged main') are flagged as unstamped without it, because a source claim nobody can date goes stale under its own author. Flag only; never a refusal. z.any() (not z.record) so a client that sends the JSON as a string is coerced in the handler — the same pattern every JSON param here uses (coerceJsonParam)."
    • changedInput schema / properties / walk / description
      Previous value: -"[stop] the walk — what you consulted, what almost answered it, the one thing only the human can supply. MANDATORY for stop; a stop without its walk is refused. ★ THE FULL-HOMEWORK GATE: the walk must NAME THE INSTRUMENTS you actually went to and what each RETURNED — the substrate (hunt/walk/open/brief), the analytics socket (any connected provider, feed or MCP tool), the repo at source, the CLIs you hold (railway/gh/neonctl), the service's own endpoints — or the named reason one is unreachable from your seat, which is itself a complete answer. A walk naming NO instrument is REFUSED and the reachable-but-unconsulted list is served back. It gates the SHAPE of the walk, never whether your reading was good enough."New value: +"[stop] the walk — what you consulted, what almost answered it, the one thing only the human can supply. MANDATORY for stop; a stop without its walk is refused. ★ THE FULL-HOMEWORK GATE: the walk must NAME THE INSTRUMENTS you actually went to and what each RETURNED — the substrate (hunt/walk/open/brief), the analytics socket (any connected provider, feed or MCP tool), the repo at source, the CLIs you hold (railway/gh/neonctl), the service's own endpoints — or the named reason one is unreachable from your agent, which is itself a complete answer. A walk naming NO instrument is REFUSED and the reachable-but-unconsulted list is served back. It gates the SHAPE of the walk, never whether your reading was good enough."
  10. Changed1 schema field changed
    • changedInput schema / properties / report / description
      Previous value: -"[run_report] the machine keys, as an object (or its JSON string): { briefs:[{id,disposition}], prs:[{number,sha,gates,merge_sha}], forks:[{candidate_id,why}], findings:[...], litter, touched:{files,branches}, verified_against:{sha,at}, production_check:{passed,build,check,at} }. A reader seat relies on these KEYS, not prose. ★ production_check IS READ BY manage_unl action=\"close_brief\": a brief whose text demands a production check closes 'completed' only when its latest run report carries production_check {passed:true, build:<the 7-40 hex sha the live site served>} — the record of the check, not a sentence about it. ★ merge_sha IS THE ONE THE REPORTLESS-MERGE WATCHER READS, and it is NOT the same as sha: sha is the head you reported at (often pre-merge), merge_sha is what the work actually LANDED as. Fill merge_sha whenever the PR merged in this run, so the record says what the work actually LANDED as. ★ THE 27 JUL DIAGNOSIS PRINTED HERE WAS WRONG AND IS CORRECTED: it blamed the 62-against-21 gap entirely on seat reporting — on this field going unnamed and seats filling sha in its place. Seats then filled merge_sha correctly and the count stayed wrong, which falsifies it. The real cause was the watcher's DENOMINATOR: it enumerated every commit on the trunk while this repo is MIXED (squash AND merge commits both enabled — 47 merge commits dragging 145 payload commits over the last 200 landings), and a payload commit can never match a report. Both halves are fixed — the watcher now enumerates the first-parent chain and matches on BOTH merge_sha and sha — so filling this field is good record-keeping, NOT a workaround for a broken reader. verified_against STAMPS the source state your claims were read against — findings that assert source state ('verified at source', 'against merged main') are flagged as unstamped without it, because a source claim nobody can date goes stale under its own author. Flag only; never a refusal. z.any() (not z.record) so a client that sends the JSON as a string is coerced in the handler — the same pattern every JSON param here uses (coerceJsonParam)."New value: +"[run_report] the machine keys, as an object (or its JSON string): { briefs:[{id,disposition}], prs:[{number,sha,gates,merge_sha}], forks:[{candidate_id,why}], findings:[...], litter, touched:{files,branches}, verified_against:{sha,at}, production_check:{passed,build,check,at} }. A reader seat relies on these KEYS, not prose. ★ production_check IS READ BY the manage_unl tool with action=\"close_brief\": a brief whose text demands a production check closes 'completed' only when its latest run report carries production_check {passed:true, build:<the 7-40 hex sha the live site served>} — the record of the check, not a sentence about it. ★ merge_sha IS THE ONE THE REPORTLESS-MERGE WATCHER READS, and it is NOT the same as sha: sha is the head you reported at (often pre-merge), merge_sha is what the work actually LANDED as. Fill merge_sha whenever the PR merged in this run, so the record says what the work actually LANDED as. ★ THE 27 JUL DIAGNOSIS PRINTED HERE WAS WRONG AND IS CORRECTED: it blamed the 62-against-21 gap entirely on seat reporting — on this field going unnamed and seats filling sha in its place. Seats then filled merge_sha correctly and the count stayed wrong, which falsifies it. The real cause was the watcher's DENOMINATOR: it enumerated every commit on the trunk while this repo is MIXED (squash AND merge commits both enabled — 47 merge commits dragging 145 payload commits over the last 200 landings), and a payload commit can never match a report. Both halves are fixed — the watcher now enumerates the first-parent chain and matches on BOTH merge_sha and sha — so filling this field is good record-keeping, NOT a workaround for a broken reader. verified_against STAMPS the source state your claims were read against — findings that assert source state ('verified at source', 'against merged main') are flagged as unstamped without it, because a source claim nobody can date goes stale under its own author. Flag only; never a refusal. z.any() (not z.record) so a client that sends the JSON as a string is coerced in the handler — the same pattern every JSON param here uses (coerceJsonParam)."
  11. Changed1 schema field changed
    • changedInput schema / properties / report / description
      Previous value: -"[run_report] the machine keys, as an object (or its JSON string): { briefs:[{id,disposition}], prs:[{number,sha,gates,merge_sha}], forks:[{candidate_id,why}], findings:[...], litter, touched:{files,branches}, verified_against:{sha,at}, production_check:{passed,build,check,at} }. A reader seat relies on these KEYS, not prose. ★ production_check IS READ BY close_brief: a brief whose text demands a production check closes 'completed' only when its latest run report carries production_check {passed:true, build:<the 7-40 hex sha the live site served>} — the record of the check, not a sentence about it. ★ merge_sha IS THE ONE THE REPORTLESS-MERGE WATCHER READS, and it is NOT the same as sha: sha is the head you reported at (often pre-merge), merge_sha is what the work actually LANDED as. Fill merge_sha whenever the PR merged in this run, so the record says what the work actually LANDED as. ★ THE 27 JUL DIAGNOSIS PRINTED HERE WAS WRONG AND IS CORRECTED: it blamed the 62-against-21 gap entirely on seat reporting — on this field going unnamed and seats filling sha in its place. Seats then filled merge_sha correctly and the count stayed wrong, which falsifies it. The real cause was the watcher's DENOMINATOR: it enumerated every commit on the trunk while this repo is MIXED (squash AND merge commits both enabled — 47 merge commits dragging 145 payload commits over the last 200 landings), and a payload commit can never match a report. Both halves are fixed — the watcher now enumerates the first-parent chain and matches on BOTH merge_sha and sha — so filling this field is good record-keeping, NOT a workaround for a broken reader. verified_against STAMPS the source state your claims were read against — findings that assert source state ('verified at source', 'against merged main') are flagged as unstamped without it, because a source claim nobody can date goes stale under its own author. Flag only; never a refusal. z.any() (not z.record) so a client that sends the JSON as a string is coerced in the handler — the same pattern every JSON param here uses (coerceJsonParam)."New value: +"[run_report] the machine keys, as an object (or its JSON string): { briefs:[{id,disposition}], prs:[{number,sha,gates,merge_sha}], forks:[{candidate_id,why}], findings:[...], litter, touched:{files,branches}, verified_against:{sha,at}, production_check:{passed,build,check,at} }. A reader seat relies on these KEYS, not prose. ★ production_check IS READ BY manage_unl action=\"close_brief\": a brief whose text demands a production check closes 'completed' only when its latest run report carries production_check {passed:true, build:<the 7-40 hex sha the live site served>} — the record of the check, not a sentence about it. ★ merge_sha IS THE ONE THE REPORTLESS-MERGE WATCHER READS, and it is NOT the same as sha: sha is the head you reported at (often pre-merge), merge_sha is what the work actually LANDED as. Fill merge_sha whenever the PR merged in this run, so the record says what the work actually LANDED as. ★ THE 27 JUL DIAGNOSIS PRINTED HERE WAS WRONG AND IS CORRECTED: it blamed the 62-against-21 gap entirely on seat reporting — on this field going unnamed and seats filling sha in its place. Seats then filled merge_sha correctly and the count stayed wrong, which falsifies it. The real cause was the watcher's DENOMINATOR: it enumerated every commit on the trunk while this repo is MIXED (squash AND merge commits both enabled — 47 merge commits dragging 145 payload commits over the last 200 landings), and a payload commit can never match a report. Both halves are fixed — the watcher now enumerates the first-parent chain and matches on BOTH merge_sha and sha — so filling this field is good record-keeping, NOT a workaround for a broken reader. verified_against STAMPS the source state your claims were read against — findings that assert source state ('verified at source', 'against merged main') are flagged as unstamped without it, because a source claim nobody can date goes stale under its own author. Flag only; never a refusal. z.any() (not z.record) so a client that sends the JSON as a string is coerced in the handler — the same pattern every JSON param here uses (coerceJsonParam)."
  12. Changed3 schema fields changed
    • changedInput schema / properties / pack_id / description
      Previous value: -"[run_report] the PACK this run executed (id or unique id-prefix, brief bac602cc) — cited in the report and marks the pack complete, closing the loop from dispatch to outcome. The per-item dispositions ride report.briefs[].disposition. Omit for a run that was not dispatched as a pack."New value: +"[run_report] the PACK this run executed (id or unique id-prefix) — cited in the report and marks the pack complete, closing the loop from dispatch to outcome. The per-item dispositions ride report.briefs[].disposition. Omit for a run that was not dispatched as a pack."
    • changedInput schema / properties / report / description
      Previous value: -"[run_report] the machine keys, as an object (or its JSON string): { briefs:[{id,disposition}], prs:[{number,sha,gates,merge_sha}], forks:[{candidate_id,why}], findings:[...], litter, touched:{files,branches}, verified_against:{sha,at}, production_check:{passed,build,check,at} }. A reader seat relies on these KEYS, not prose. ★ production_check IS READ BY close_brief (12c26fee): a brief whose text demands a production check closes 'completed' only when its latest run report carries production_check {passed:true, build:<the 7-40 hex sha the live site served>} — the record of the check, not a sentence about it. ★ merge_sha IS THE ONE THE REPORTLESS-MERGE WATCHER READS, and it is NOT the same as sha: sha is the head you reported at (often pre-merge), merge_sha is what the work actually LANDED as. Fill merge_sha whenever the PR merged in this run, so the record says what the work actually LANDED as. ★ THE 27 JUL DIAGNOSIS PRINTED HERE WAS WRONG AND IS CORRECTED (brief 2da7fe29): it blamed the 62-against-21 gap entirely on seat reporting — on this field going unnamed and seats filling sha in its place. Seats then filled merge_sha correctly and the count stayed wrong, which falsifies it. The real cause was the watcher's DENOMINATOR: it enumerated every commit on the trunk while this repo is MIXED (squash AND merge commits both enabled — 47 merge commits dragging 145 payload commits over the last 200 landings), and a payload commit can never match a report. Both halves are fixed — the watcher now enumerates the first-parent chain and matches on BOTH merge_sha and sha — so filling this field is good record-keeping, NOT a workaround for a broken reader. verified_against STAMPS the source state your claims were read against — findings that assert source state ('verified at source', 'against merged main') are flagged as unstamped without it, because a source claim nobody can date goes stale under its own author (ecaea91e). Flag only; never a refusal. z.any() (not z.record) so a client that sends the JSON as a string is coerced in the handler — the same pattern every JSON param here uses (coerceJsonParam)."New value: +"[run_report] the machine keys, as an object (or its JSON string): { briefs:[{id,disposition}], prs:[{number,sha,gates,merge_sha}], forks:[{candidate_id,why}], findings:[...], litter, touched:{files,branches}, verified_against:{sha,at}, production_check:{passed,build,check,at} }. A reader seat relies on these KEYS, not prose. ★ production_check IS READ BY close_brief: a brief whose text demands a production check closes 'completed' only when its latest run report carries production_check {passed:true, build:<the 7-40 hex sha the live site served>} — the record of the check, not a sentence about it. ★ merge_sha IS THE ONE THE REPORTLESS-MERGE WATCHER READS, and it is NOT the same as sha: sha is the head you reported at (often pre-merge), merge_sha is what the work actually LANDED as. Fill merge_sha whenever the PR merged in this run, so the record says what the work actually LANDED as. ★ THE 27 JUL DIAGNOSIS PRINTED HERE WAS WRONG AND IS CORRECTED: it blamed the 62-against-21 gap entirely on seat reporting — on this field going unnamed and seats filling sha in its place. Seats then filled merge_sha correctly and the count stayed wrong, which falsifies it. The real cause was the watcher's DENOMINATOR: it enumerated every commit on the trunk while this repo is MIXED (squash AND merge commits both enabled — 47 merge commits dragging 145 payload commits over the last 200 landings), and a payload commit can never match a report. Both halves are fixed — the watcher now enumerates the first-parent chain and matches on BOTH merge_sha and sha — so filling this field is good record-keeping, NOT a workaround for a broken reader. verified_against STAMPS the source state your claims were read against — findings that assert source state ('verified at source', 'against merged main') are flagged as unstamped without it, because a source claim nobody can date goes stale under its own author. Flag only; never a refusal. z.any() (not z.record) so a client that sends the JSON as a string is coerced in the handler — the same pattern every JSON param here uses (coerceJsonParam)."
    • changedInput schema / properties / walk / description
      Previous value: -"[stop] the fd82564d walk — what you consulted, what almost answered it, the one thing only the human can supply. MANDATORY for stop; a stop without its walk is refused. ★ THE FULL-HOMEWORK GATE (732d5dd5): the walk must NAME THE INSTRUMENTS you actually went to and what each RETURNED — the substrate (hunt/walk/open/brief), the analytics socket (any connected provider, feed or MCP tool), the repo at source, the CLIs you hold (railway/gh/neonctl), the service's own endpoints — or the named reason one is unreachable from your seat, which is itself a complete answer. A walk naming NO instrument is REFUSED and the reachable-but-unconsulted list is served back. It gates the SHAPE of the walk, never whether your reading was good enough."New value: +"[stop] the walk — what you consulted, what almost answered it, the one thing only the human can supply. MANDATORY for stop; a stop without its walk is refused. ★ THE FULL-HOMEWORK GATE: the walk must NAME THE INSTRUMENTS you actually went to and what each RETURNED — the substrate (hunt/walk/open/brief), the analytics socket (any connected provider, feed or MCP tool), the repo at source, the CLIs you hold (railway/gh/neonctl), the service's own endpoints — or the named reason one is unreachable from your seat, which is itself a complete answer. A walk naming NO instrument is REFUSED and the reachable-but-unconsulted list is served back. It gates the SHAPE of the walk, never whether your reading was good enough."
  13. First observed

TDQS

B3.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations present (readOnlyHint=false, destructiveHint=false, idempotentHint=false), the description still adds real behavioral context: the single-use nonce and its 600s expiry, 'there is no session-close — write at the beat or it's lost', handoff 'replaces the last', the stop escalates ONCE only after a patience window, and the walk/why/considered gates that REFUSE malformed writes. It does not spell out non-idempotency in the description itself, so a 4.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single enormous paragraph front-loads the verb correctly, but the report parameter description alone is a multi-hundred-word digression into a dated diagnosis ('THE 27 JUL DIAGNOSIS PRINTED HERE WAS WRONG'), watcher denominators and merge-commit statistics. Much of the text is incident forensics rather than call guidance, and the kind-by-kind structure is buried in a wall of prose rather than front-loaded or separated.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a 31-parameter, seven-mode mutation tool with no output schema, but the rich schema descriptions compensate substantially and the description covers the nonce flow and per-kind gates. What it omits is the return shape (what nonce or ids come back after a write, mattering since subsequent writes need a fresh nonce) and explicit routing against the four sibling write tools. Complete enough to call, not complete enough to call confidently on the first try.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the per-parameter descriptions already carry mandatory flags, enums and per-kind applicability. The description restates the mandatory-field requirements (why, walk, reason, considered+why_ruled_out, message, outcome_result) which is useful cross-checking, but adds little meaning beyond what the schema states. Baseline 3 is correct.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource ('Log an outbound beat to your Unlimitless substrate') and enumerates seven kinds, each given its own semantics. It differentiates itself from ask_unl/connect_to_unl (reads and connections) and manage_unl by being the outbound write surface, though it never explicitly names those siblings. The purpose is clear but the sibling routing is left implicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Per-kind guidance is rich: momentum is 'ONE settled, AIM-MOVING beat a cold agent wakes from', rejection is 'only the deliberate ruling-out, not passing tangents', the stop 'fires NO knock now — the attended case stays silent'. However, there is no explicit statement of when to choose log_to_unl over save_to_unl or write_to_tool, nor when not to write at all. Usage is heavily implied rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.