← Roadmap Ledger
API
Tokens

Run Roadmap Ledger from your own code

Both metered lanes are available over HTTP and each returns one JSON object. The division of labour: the page ranks the six publication postures, runs every item through the exclusion gate, caps every date with a phase, finds silent removals and unclosed shipped items and ranks the feedback surface, then hands it all to the run as facts. The run writes the roadmap policy or the slip notices; the page then holds it to its own facts (rlreply.js).

Base URL and the response shape

Every endpoint lives under https://api.skillsafe.ai/v1/app-api, and every response has one shape:

{ "ok": true,  "data":  { ... } }
{ "ok": false, "error": { "code": "...", "message": "..." } }

The token is minted for this app (the guest call takes {"slug":"roadmap-ledger"}), so no slug header is needed afterwards. Send it as Authorization: Bearer YOUR_TOKEN. The run body is the input object, sent bare.

StatusCodeMeaning
400validation_errorThe body is not a JSON object, or a required key (task, company, items, facts) is missing. The page always sends all five of task, company, items, carry, facts; carry is an empty string for policy.
401unauthorizedNo token, or a stale one. Mint a guest token or sign in again.
402insufficient_creditsThe balance is under min_credits. Price with /estimate first.
403forbiddenA guest token tried to run: both lanes are metered and need a personal sign-in.
404not_foundUnknown job id.
429rate_limitedBack off and retry.
5xxserver_errorTransient. Retry with the same Idempotency-Key so a retry never double-bills.

The task field comes first

Two lanes, chosen by task, in the order the work runs - before anything goes public, then when an item slips:

A missing or unknown task is answered as policy. Both lanes send the same five fields. The facts are the page's checks, one row per line, and a line starting "must:" is a rule the reply has to hold. The page's handoff carries the policy's decisions into carry for the slips lane.

The input

FieldRequiredWhat
taskyespolicy or slips. If it is missing or neither, do policy and set "task": "policy".
companyyesthe company, the trigger, buyers, listing, regulation, release machinery, the slip rate, contracts and clauses, the citation rule, feedback today, the owner and hours, cadence, deadline and effort; "not given" means not given.
itemsyesevery roadmap item with its phase, date, category, status, changelog link, reviews since touched, who was told, and the page's flags.
carrysend it (empty for policy)slips task only: the policy's decisions, when the policy task ran first; may be empty.
factsyesthe page's checks, one line each as area | id | status | evidence, the verdict and the ranked postures. A line starting "must:" applies to your reply.
retry_notenooptional; if present, your previous reply was unusable - follow it.

The rules the model applies

From the source skill, @samber/public-roadmap-strategy - the only standard the run applies:

House rules

The replies

policy

Write the roadmap policy - the posture, what each state promises, what never goes public, the guardrails, the feedback surface and who keeps it current.

  1. summary - one sentence, at most 40 words: the posture, and what must happen before anything is published.
  2. posture - recommended and alternative (horizon, direction, none, briefings, board or dated, exactly as the facts rank them), bundle (the bundled posture the facts name, else empty), why (one sentence naming the reasons the facts give for this ranking).
  3. vocabulary - family (buckets, phases, quarters, themes or none, exactly as the facts read it), states (objects: state, meaning - what a customer may rely on; list the family's own states - each release phase, each bucket or each quarter-with-phase the items use - and include a not planned state; when the items include a community proposal, add a state that labels proposals apart from vendor plans; quarters always carry a phase; [] when the family is none).
  4. gate - one object per item the facts keep off the page, in their order: item (as written), reason (one sentence).
  5. guardrails - disclaimer (one sentence in this company's voice, as it would sit on its page; the standard phrases not a commitment and subject to change are expected here), clause (one sentence: the contract clause and the self-serve equivalent), citation (short strings: the citation rules, each written for this company - name who signs and enforces it, the channels its reps use, and its own items or contracts where they apply), forward_looking (one sentence for a listed company, else empty).
  6. feedback - surface (locked, reactions, board or frozen, exactly as the facts read it), why (one sentence).
  7. lifecycle - owner (the owner as given, else "unassigned - name one"), cadence (one sentence), close (one sentence: shipped items closed with a changelog link).
  8. caveats - at most 4 short strings; [] when there is nothing to say.
{
  "task": "policy",
  "summary": "one sentence",
  "posture": { "recommended": "horizon", "alternative": "direction", "bundle": "", "why": "one sentence" },
  "vocabulary": { "family": "phases", "states": [ { "state": "Private preview", "meaning": "one sentence" } ] },
  "gate": [ { "item": "as written", "reason": "one sentence" } ],
  "guardrails": { "disclaimer": "one sentence", "clause": "one sentence", "citation": [ "a short string" ], "forward_looking": "" },
  "feedback": { "surface": "locked", "why": "one sentence" },
  "lifecycle": { "owner": "a name", "cadence": "one sentence", "close": "one sentence" },
  "caveats": [ ]
}

The page holds it to its own facts (check() in rlreply.js; any warning makes the reply flagged): the reply answers the task it was sent; no URL; no backticks; a summary of at most 40 words; the page's posture, alternative and bundle; its vocabulary family, with at least three states including a not planned state (and every quarter capped by a phase) unless the family is none; exactly the gated items in the page's order, each with a reason; a disclaimer saying not a commitment and subject to change; the contract clause; at least three citation rules; forward-looking-statement language for a listed company; the page's feedback surface; the owner as given, or a call to name one; a cadence; shipped items closed with a changelog link; at most four caveats.

slips

Write the notice for every slipped, descoped, cancelled or silently removed item.

  1. summary - one sentence, at most 40 words.
  2. slips - one object per slipped item, in the facts' order: item (as written), status (delayed, descoped or not planned - exactly as the facts read it; a removed item is restored with one of the three - delayed when the input suggests the work is still intended, not planned when it shows the item was dropped; when it shows neither, restore it as delayed and tell readers when its future will be settled, using the company's own review cadence), reason (one or two sentences, plain language), workaround (one sentence: an alternative the input names, or else what to do meanwhile in plain terms - keep the current approach, subscribe for the next update, talk to the account owner; never invent a product or feature), notify (short strings: subscribers, reactors only when the feedback surface is reactions, the accounts the briefing log shows - each item's customers-told value is that log: deck or NDA audiences are briefed accounts - and, for an item a contract names, the contract customers through their account owner), private_first (true when a contract names the item - the account owner tells that customer days before the public update).
  3. caveats - at most 4 short strings; [] when there is nothing to say.
{
  "task": "slips",
  "summary": "one sentence",
  "slips": [ { "item": "as written", "status": "delayed", "reason": "one or two sentences", "workaround": "one sentence", "notify": [ "subscribers" ], "private_first": false } ],
  "caveats": [ ]
}

The page requires: the reply answers the task it was sent; the same text rules; exactly the page's slipped items in its order; each status as the page reads it (a vanished item restored as delayed, descoped or not planned); a reason and a workaround each; subscribers notified; private first exactly when a contract names the item; and no item ever deleted.

Worked examples

Three runs from the page's free samples (invented companies): the policy for a webhook API whose sales team promises unbuilt features, the slip notices for the same company carrying that policy, and the policy for a listed platform ready for dated quarters. Each input is exactly what the page sends; each reply is the saved reply the sample replays, shipped unedited - but the facts and long strings are shortened in this display only, and every cut is listed under the example. The last line is the page's own check of the full reply.

policy - A webhook API whose sales team promises

The page read it as: fix sales governance before any public page; postures none, briefings; vocabulary none; feedback frozen; 0 of 5 gates; failing checks: citation, contracts, revrec, exclusion, dates, visible, lifecycle, board.

Input (facts is 2770 characters; the first 1395 are shown):

{
 "task": "policy",
 "company": "Company: Hookwend\nThe product and why a roadmap now: A webhook delivery API; the CEO wants a public roadmap because reps keep promising features from the internal one.\nTrigger: Sales keeps promising unbuilt features; benchmark named: not given; buyers: Both; listed: no; regulated customers: no; open-core with public issues: no\nRelease phases exist: no; changelog: yes; committed items slipped last year: 40%; buyers plan around dates: no; finance reviewed revenue recognition: no\nMSA not-contingent clause: no; self-serve equivalent: no; contracts naming roadmap items: 2; leadership signs the citation rule: no\nFeedback today: A board nobody triages; owner: not given; owner hours a month: 2; review cadence: None; deadline: no; a standing practice; effort ceiling: low; as-of: 2026-11-01",
 "items": "Items in the order given (item | phase | date | category | status | changelog | reviews since touched | told):\n- Replay failed deliveries from the dashboard | A horizon bucket (Next) | Q1 | a customer-facing capability | planned | changelog no | 3 reviews since touched | customers told: deck | BARE DATE\n- Webhook signing v2 | A horizon bucket (Now) | undated | a customer-facing capability | delayed | changelog no | 1 review since touched | customers told: contract | SLIP - contract customers hear privately first | solution-named\n- Retry webhooks for 7 days | A horizon bucket (Later) | undated | a customer-facing capability | removed without a state | changelog no | 4 reviews since touched | customers told: deck | SLIP\n- Patch the signature timing leak | A horizon bucket (Now) | undated | a security fix or hardening | planned | changelog no | 0 reviews since touched | customers told: none | OFF THE PAGE",
 "carry": "",
 "facts": "The page's checks (8 fail, 4 warn, 0 pass, 2 n/a); verdict: fix sales governance before any public page:\n- Posture and guardrails | posture | na | No public roadmap first, customer briefings under NDA as the alternative - sales promise unbuilt features and leadership will not sign the citation rule - every public posture is deleted until the rule is signed; an enterprise audience moves customer briefings up the value ranking\n- Posture and guardrails | citation | fail | sales promise unbuilt features and nobody signs the rule - publishing hands reps a larger catalogue to promise from\n- Posture and guardrails | contracts | fail | 2 order forms or side letters name roadmap items - binding whatever the disclaimer says; counsel and finance review each, the account owner calls the customer\n- Posture and guardrails | clause | warn | no clause - counsel decides whether to add it to new and renewing contracts\n- Posture and guardrails | selfserve | warn | an MSA clause does not cover click-through accounts\n- Posture and guardrails | revrec | fail | dated, named features can create a specified-upgrade obligation - bring finance in before any date reaches a customer\n- The items | exclusion | fail | Patch the signature timing leak (a security fix or hardening)\n- The items | dates | fail | Replay failed deliveries from the dashboard (Q1, a horizon bucket) - a bare quarter reads as GA to\n\n[... 1375 more characters cut from this display ...]"
}

Reply:

{
 "task": "policy",
 "summary": "Publish no public roadmap for now and brief customers under NDA instead; before any page goes live, the sales leader and the CEO must sign the citation rule and counsel must review the 2 contracts naming roadmap items.",
 "posture": {
  "recommended": "none",
  "alternative": "briefings",
  "bundle": "",
  "why": "Reps already promise unbuilt features and leadership will not sign the citation rule, so every public posture is deleted until sales governance is fixed, leaving no public roadmap first and NDA customer briefings as the alternative."
 },
 "vocabulary": {
  "family": "none",
  "states": []
 },
 "gate": [
  {
   "item": "Patch the signature timing leak",
   "reason": "It is a security fix, and naming it before it ships tells attackers where the weakness is."
  }
 ],
 "guardrails": {
  "disclaimer": "Anything shared about future plans is informational only, is not a commitment, is subject to change and must not be relied on for purchasing decisions.",
  "clause": "Counsel should decide whether new and renewing contracts state that purchases are not contingent on future functionality, with the same statement in the click-through terms, since Hookwend has neither today.",
  "citation": [
   "No rep cites a roadmap item until the sales leader and the CEO sign this rule.",
   "Previews of future work happen only in NDA briefings with product present.",
   "No dates for any item in decks, emails or calls.",
   "Legal and finance approve any roadmap item before it enters an order form.",
   "Any deal that depends on an unbuilt feature goes to product, not to the rep."
  ],
  "forward_looking": ""
 },
 "feedback": {
  "surface": "frozen",
  "why": "Nobody triages the current board, so freeze it read-only behind a dated notice that points to one feedback channel, and plan its exit before the next launch."
 },
 "lifecycle": {
  "owner": "unassigned - name one",
  "cadence": "There is no review cadence today; the named owner and a backup should review every item, including the briefing deck, at a fixed interval and snapshot it each time.",
  "close": "Every shipped item is closed with a changelog link, which the existing changelog makes possible."
 },
 "caveats": [
  "Two order forms or side letters name roadmap items and bind Hookwend whatever any disclaimer says; counsel and finance review each and the account owner calls the customer.",
  "Committed items slipped 40% of the time last year, so even briefings should carry no dates; Replay failed deliveries from the dashboard already shows a bare Q1.",
  "Retry webhooks for 7 days vanished from the deck; restore it as delayed, descoped or not planned rather than leave it gone.",
  "Finance has not reviewed revenue-recognition exposure; bring them in before any date reaches a customer."
 ]
}

What step 5 prints for it: none: Publish no public roadmap for now and brief customers under NDA instead; before any page goes live, the sales leader and the CEO must sign the citation rule and counsel must review the 2 contracts naming roadmap items.

The page's check: kept - nothing to flag

slips - A webhook API whose sales team promises

The input carries the saved policy's decisions (R.laneForm fills carry from the policy reply), as the page's handoff does. The slipped items in order: wire, wireShown, wireNote, reply, shown, cuts, status, notes, carried, gist.

Input (facts is 2778 characters; the first 1395 are shown):

{
 "task": "slips",
 "company": "Company: Hookwend\nThe product and why a roadmap now: A webhook delivery API; the CEO wants a public roadmap because reps keep promising features from the internal one.\nTrigger: Sales keeps promising unbuilt features; benchmark named: not given; buyers: Both; listed: no; regulated customers: no; open-core with public issues: no\nRelease phases exist: no; changelog: yes; committed items slipped last year: 40%; buyers plan around dates: no; finance reviewed revenue recognition: no\nMSA not-contingent clause: no; self-serve equivalent: no; contracts naming roadmap items: 2; leadership signs the citation rule: no\nFeedback today: A board nobody triages; owner: not given; owner hours a month: 2; review cadence: None; deadline: no; a standing practice; effort ceiling: low; as-of: 2026-11-01",
 "items": "Items in the order given (item | phase | date | category | status | changelog | reviews since touched | told):\n- Replay failed deliveries from the dashboard | A horizon bucket (Next) | Q1 | a customer-facing capability | planned | changelog no | 3 reviews since touched | customers told: deck | BARE DATE\n- Webhook signing v2 | A horizon bucket (Now) | undated | a customer-facing capability | delayed | changelog no | 1 review since touched | customers told: contract | SLIP - contract customers hear privately first | solution-named\n- Retry webhooks for 7 days | A horizon bucket (Later) | undated | a customer-facing capability | removed without a state | changelog no | 4 reviews since touched | customers told: deck | SLIP\n- Patch the signature timing leak | A horizon bucket (Now) | undated | a security fix or hardening | planned | changelog no | 0 reviews since touched | customers told: none | OFF THE PAGE",
 "carry": "Posture: none\nVocabulary: none (no public states)\nFeedback: frozen\nOwner: unassigned - name one; cadence: There is no review cadence today; the named owner and a backup should review every item, including the briefing deck, at a fixed interval and snapshot it each time.\nCitation: No rep cites a roadmap item until the sales leader and the CEO sign this rule. | Previews of future work happen only in NDA briefings with product present. | No dates for any item in decks, emails or calls. | Legal and finance approve any roadmap item before it enters an order form. | Any deal that depends on an unbuilt feature goes to product, not to the rep.",
 "facts": "The page's checks (8 fail, 4 warn, 0 pass, 2 n/a); verdict: fix sales governance before any public page:\n- Posture and guardrails | posture | na | No public roadmap first, customer briefings under NDA as the alternative - sales promise unbuilt features and leadership will not sign the citation rule - every public posture is deleted until the rule is signed; an enterprise audience moves customer briefings up the value ranking\n- Posture and guardrails | citation | fail | sales promise unbuilt features and nobody signs the rule - publishing hands reps a larger catalogue to promise from\n- Posture and guardrails | contracts | fail | 2 order forms or side letters name roadmap items - binding whatever the disclaimer says; counsel and finance review each, the account owner calls the customer\n- Posture and guardrails | clause | warn | no clause - counsel decides whether to add it to new and renewing contracts\n- Posture and guardrails | selfserve | warn | an MSA clause does not cover click-through accounts\n- Posture and guardrails | revrec | fail | dated, named features can create a specified-upgrade obligation - bring finance in before any date reaches a customer\n- The items | exclusion | fail | Patch the signature timing leak (a security fix or hardening)\n- The items | dates | fail | Replay failed deliveries from the dashboard (Q1, a horizon bucket) - a bare quarter reads as GA to\n\n[... 1383 more characters cut from this display ...]"
}

Reply:

{
 "task": "slips",
 "summary": "Two notices: Webhook signing v2 is delayed and its contract customers hear privately first; Retry webhooks for 7 days, which vanished without a state, is restored as delayed and stays visible.",
 "slips": [
  {
   "item": "Webhook signing v2",
   "status": "delayed",
   "reason": "This work is taking longer than planned and will not land in the current window. It stays on the list as delayed, and we will share a new phase once one is firm.",
   "workaround": "Keep verifying deliveries with the signing you use today; nothing changes for existing integrations while this is delayed.",
   "notify": [
    "subscribers",
    "contract customers who have it in their order form",
    "the account owner for each of those contract customers"
   ],
   "private_first": true
  },
  {
   "item": "Retry webhooks for 7 days",
   "status": "delayed",
   "reason": "This item disappeared from the list without any explanation, which was a mistake. It is now restored with a visible delayed state: it has not been worked on recently and has no new timing yet.",
   "workaround": "Meanwhile, keep your own handling for deliveries that fail, and subscribe to this item to hear when its state changes.",
   "notify": [
    "subscribers",
    "accounts shown the briefing deck"
   ],
   "private_first": false
  }
 ],
 "caveats": [
  "There is no public page yet, so these states go into the briefing deck and direct notices, never a new public roadmap.",
  "Counsel and finance review both order forms before the account owner calls; the public update waits days after that call.",
  "No owner is named yet - name one and a backup before these notices go out.",
  "This is not legal advice; route the final wording to counsel."
 ]
}

What step 5 prints for it: Webhook signing v2 delayed | Retry webhooks for 7 days delayed

The page's check: kept - nothing to flag

policy - A listed platform ready for dated quarters

The page read it as: a roadmap you can publish and keep; postures dated, horizon, direction, briefings, none, board (bundled with briefings); vocabulary quarters; feedback locked; 5 of 5 gates; failing checks: none.

Input (facts is 1932 characters; the first 1397 are shown):

{
 "task": "policy",
 "company": "Company: Beaconmere\nThe product and why a roadmap now: A listed observability platform; enterprise buyers plan migrations around the roadmap and procurement asks for it.\nTrigger: Customers and prospects keep asking what's coming; benchmark named: like Stripe; buyers: Mostly enterprise buyers under negotiated contracts; listed: yes; regulated customers: yes; open-core with public issues: no\nRelease phases exist: yes; changelog: yes; committed items slipped last year: 8%; buyers plan around dates: yes; finance reviewed revenue recognition: yes\nMSA not-contingent clause: yes; self-serve equivalent: yes; contracts naming roadmap items: not given; leadership signs the citation rule: yes\nFeedback today: No board; owner: Ruth Achebe; owner hours a month: 20; review cadence: Monthly; deadline: no; a standing practice; effort ceiling: high; as-of: 2026-11-01",
 "items": "Items in the order given (item | phase | date | category | status | changelog | reviews since touched | told):\n- Trace sampling you can set per service | Private preview | Q1 2027 | a customer-facing capability | planned | changelog no | 0 reviews since touched | customers told: none\n- Alert on budget burn, not raw errors | Public preview | Q2 2027 | a customer-facing capability | planned | changelog no | 0 reviews since touched | customers told: none\n- Logs retained 13 months | GA | undated | a customer-facing capability | shipped | changelog yes | 0 reviews since touched | customers told: none\n- Dashboards as code | Exploring | undated | a customer-facing capability | not planned | changelog no | 0 reviews since touched | customers told: deck | SLIP",
 "carry": "",
 "facts": "The page's checks (0 fail, 1 warn, 6 pass, 2 n/a); verdict: a roadmap you can publish and keep:\n- Posture and guardrails | posture | na | Dated quarters first, horizon roadmap as the alternative, bundled with customer briefings under NDA - phases exist, the slip rate is low, buyers plan around dates and finance signed off - dated quarters, capped by phase; regulated enterprise buyers - bundle NDA customer briefings with the public page; an enterprise audience moves customer briefings up the value ranking\n- Posture and guardrails | citation | pass | the sales leader and the CEO sign and enforce it\n- Posture and guardrails | safeharbor | warn | add securities safe-harbor language and run roadmap statements through disclosure review\n- Posture and guardrails | revrec | pass | finance reviewed revenue-recognition exposure\n- The items | exclusion | pass | 4 items, each a customer-facing capability\n- The items | dates | pass | every dated item has entered private preview or later\n- The items | visible | pass | every slip carries a state\n- Lifecycle and measurement | lifecycle | pass | owner Ruth Achebe; monthly reviews; 1 of 1 shipped item closed with a changelog link\n- Lifecycle and measurement | measures | na | freshness 100%; silent removals 0; close rate 100%; slip rate 25% of committed items\nPostures by the skill's ranking, in order: dated, horizon, direction, briefings, none,\n\n[... 535 more characters cut from this display ...]"
}

Reply (long strings shortened for display - see the cuts below):

{
 "task": "policy",
 "summary": "Publish a dated-quarters roadmap with every quarter capped by its release phase, bundled with NDA customer briefings; before it goes live, add safe-harbor language and run the page through disclosure review.",
 "posture": {
  "recommended": "dated",
  "alternative": "horizon",
  "bundle": "briefings",
  "why": "Beaconmere has release phases, slipped only 8% of committed items last year, sells to enterprise buyers who plan migrations around dates and has finance sign-off on revenue recognition, so publish dated quarters capped by phase, with a horizon [... 67 more characters cut from this display]"
 },
 "vocabulary": {
  "family": "quarters",
  "states": [
   {
    "state": "Exploring, undated",
    "meaning": "We are studying the problem; it carries no quarter and no promise that it will be built."
   },
   {
    "state": "In design, undated",
    "meaning": "We are shaping a solution; scope can still change and no quarter is shown until it reaches private preview."
   },
   {
    "state": "Private preview, target quarter",
    "meaning": "Invited customers can try it now; the quarter is our target for the next phase, not a GA date, and it may move."
   },
   {
    "state": "Public preview, target quarter",
    "meaning": "Any customer can use it under preview terms; the quarter is our target for GA, and the interface may still change before then."
   },
   {
    "state": "GA",
    "meaning": "Generally available and fully supported, closed out with a changelog entry."
   },
   {
    "state": "Not planned",
    "meaning": "We have decided not to build this; the item stays visible with its reason for at least one review cycle."
   }
  ]
 },
 "gate": [],
 "guardrails": {
  "disclaimer": "This roadmap is informational only, is not a commitment, is subject to change and must not be relied on for purchasing decisions.",
  "clause": "Keep the MSA clause that purchases are not contingent on future functionality and its matching statement in the self-serve terms, and have counsel inventory every order form for named roadmap items, which bind Beaconmere whatever the [... 17 more characters cut from this display]",
  "citation": [
   "Cite only the public roadmap, at the phase and quarter it shows.",
   "Deeper previews only in NDA briefings with product present.",
   "No dates anywhere the page does not show them.",
   "Legal and finance approve any roadmap item before it enters an order form.",
   "Any deal that depends on an unbuilt feature goes to product."
  ],
  "forward_looking": "This roadmap contains forward-looking statements about planned products and timing that involve risks and uncertainties, actual results may differ materially, and Beaconmere undertakes no obligation to update them."
 },
 "feedback": {
  "surface": "locked",
  "why": "There is no board today, so lock each item and keep debate in one channel rather than launching a voting board nobody is named to triage."
 },
 "lifecycle": {
  "owner": "Ruth Achebe",
  "cadence": "Ruth Achebe, with a named backup, reviews every item and every quarter monthly within their 20 hours a month, moves any slipping date the same day, and snapshots the page at each review.",
  "close": "Every shipped item is closed with a changelog link, as Logs retained 13 months already is."
 },
 "caveats": [
  "Beaconmere is listed, so add securities safe-harbor language and run every roadmap statement through disclosure review before publishing.",
  "Dashboards as code is not planned and was shown in the deck; keep it visible with its reason for at least one review cycle and tell the accounts that saw it.",
  "Whether any contract names a roadmap item is not given; inventory the order forms before Trace sampling you can set per service and Alert on budget burn, not raw errors go public with quarters.",
  "The page's slip rate is 25% of committed items against 8% last year; if dates keep slipping, step down to the horizon roadmap."
 ]
}

Cut from this display only (the saved reply and the check use the full text): posture.why (306 characters, 239 shown); guardrails.clause (246 characters, 229 shown).

What step 5 prints for it: dated: Publish a dated-quarters roadmap with every quarter capped by its release phase, bundled with NDA customer briefings; before it goes live, add safe-harbor language and run the page through disclosure review.

The page's check: kept - nothing to flag

Build the input yourself

Load the engine in node (global.window = global; require("./rlkit.js"); require("./rlreply.js")), then:

const K = LedgerKit, R = LedgerReply;
const f = K.form(Object.assign(K.blank(), { name: "Acme", owner: "Ann", hours: "6", phases: "yes",
  items: "Faster cold starts | In design | Q1 2027 | feature | planned | no | 0 | none\nClose the SSRF hole | Now | | security | planned | no | 0 | none\nOld export | Later | | feature | removed | no | 2 | deck" }));
// f.rank (the ranked postures, the alternative and any bundle), f.family, f.surface, f.itemRows, f.excluded, f.slipped, f.gate
// K.ledgerMd(f), K.itemsCsv(f) - the public ledger draft and the items
const b = K.buildInput(f, "policy");                         // or "slips" (R.laneForm(form, "slips", policy) fills carry)
const wire = K.toWire(b.input);                              // POST this to /estimate and /run
// then: const reply = R.normalize(R.parseReply(job.output.output), "policy");
// R.check(reply, b)                                         // {status: kept or flagged, notes}

Get a token for the steps below from /tokens.html.

Step 1 — a tiny client helper

One function that sends JSON and unwraps the response. Paste a personal token from /tokens.html, or leave it empty and mint a guest token in step 2.

BASE="https://api.skillsafe.ai/v1/app-api"
TOKEN="YOUR_TOKEN"   # from https://roadmap-ledger.skillsafe.ai/tokens.html
api() { # api METHOD PATH [JSON-BODY]
  curl -s -X "$1" "$BASE$2" -H "Content-Type: application/json" \
    ${TOKEN:+-H "Authorization: Bearer $TOKEN"} ${3:+--data "$3"}
}

Step 2 — a token

A guest token is enough for /me and /estimate. A run is metered, so it needs a personal token: sign in on /tokens.html and copy it from there.

# a guest token (enough for /me and /estimate); a run needs your personal token from /tokens.html
TOKEN=$(curl -s -X POST "$BASE/guest" -H "Content-Type: application/json" -d '{"slug":"roadmap-ledger"}' | jq -r '.data.token')

Step 3 — GET /me

Who the token is (subject_type: user or guest) and the credit balance.

api GET /me | jq '.data | {subject_type, credits}' 

Step 4 — POST /estimate

Free. The body is the run input itself, the bare object (never wrapped in {"input": ...}). hold_credits is a reservation, not the price; min_credits is what the balance must cover; model_alias reads gpt-terra.

# input.json: the run input object - {"task": "policy", "company": "Company: Hookwend
The product and why a roadmap now: ...", "items": "Items in the order given (item | phase | date | category | status | changelog | reviews since touched | told):
- Replay failed deliveries from the dashboard | ...", "carry": "", "facts": "The page's checks (...); verdict: fix sales governance before any public page:
- Posture and guardrails | posture | na | ..."}
# - see the input table
api POST /estimate "$(cat input.json)" | jq '.data | {hold_credits, min_credits, model, model_alias, markup_bps, warnings}' 

Step 5 — POST /run, then poll the job

Send an Idempotency-Key built from the lane and the input: a retry with the same key never bills twice. The page uses roadmap-ledger:<task>:<inputHash>:a<attempt> - the lane is part of the key, retry_note is left out of the hash - and its one automatic reformat retry is a new attempt number, named in the page as one extra run. A policy reply carries summary, posture, vocabulary, gate, guardrails, feedback, lifecycle and caveats; a slips reply carries summary, slips and caveats. The code below prints the gist of either: the posture and the summary, or each slipped item and its status.

KEY="roadmap-ledger:$(jq -r .task input.json):$(shasum -a 256 input.json | cut -c1-16):a1"
JOB=$(curl -s -X POST "$BASE/run" -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \
  -H "Idempotency-Key: $KEY" --data @input.json | jq -r '.data.job_id')
while :; do
  J=$(api GET "/jobs/$JOB"); S=$(echo "$J" | jq -r '.data.status')
  case "$S" in succeeded|failed|cancelled) break;; esac; sleep 2
done
echo "$J" | jq -r '.data.output.output' > reply.json   # one JSON object, the reply contract
echo "$J" | jq '.data | {charged_credits, truncated}'
jq -r 'if .task == "slips" then (.slips[] | "\(.item): \(.status)") 
       else "\(.posture.recommended): \(.summary)" end' reply.json

Step 6 — POST /run-stream

The same run as Server-Sent Events, with the same input.json. Browsers receive progress ticks rather than text deltas; the final done event carries the reply.

# Server-Sent Events: tick/delta events while the job runs, then a final event with the job
curl -N -s -X POST "$BASE/run-stream" -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \
  -H "Idempotency-Key: roadmap-ledger:$(jq -r .task input.json):$(shasum -a 256 input.json | cut -c1-16):a1" --data @input.json