← Sample Triage
API
Tokens

Run Sample Triage from your own code

Both metered lanes are available over HTTP and each returns one JSON object. The division of labour: the page triages every repo by the skill's ordered rules, sums the kept upkeep against capacity, ranks the shape, reads the freshness contract against the sandbox and gives every archive a successor, then hands it all to the run as facts. The run writes the portfolio strategy or the cleanup plan; the page then holds it to its own facts (streply.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":"sample-triage"}), 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, platform, register, facts) is missing. The page always sends all five of task, platform, register, carry, facts; carry is an empty string for strategy.
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 - what the portfolio is, then what changes now:

A missing or unknown task is answered as strategy. 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 strategy's decisions into carry for the cleanup lane.

The input

FieldRequiredWhat
taskyesstrategy or cleanup. If it is missing or neither, do strategy and set "task": "strategy".
platformyesthe platform, who integrates, the tier-1 and dominant languages, the sandbox, the usage signal, retired versions, capacity and cleanup hours, the SLA, the regulated-flow answer, deadline and policy; "not given" means not given.
registeryesevery repo with its type, job, languages, pins, owner, CI, usage, tickets, links and the page's verdict and successor, then the kept upkeep.
carrysend it (empty for strategy)cleanup task only: the strategy's decisions, when the strategy task ran first; may be empty.
factsyesthe page's checks, one line each as area | id | status | evidence, the verdict and the ranked shapes. 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/sample-app-strategy - the only standard the run applies:

House rules

The replies

strategy

Write the portfolio strategy - which artifacts exist for which job, in which languages, kept green how, archived when. A number the input does not give is a proposal: start it with "Proposed: ".

  1. summary - one sentence, at most 40 words: the shape, the cut, and what blocks the portfolio first.
  2. shape - recommended and alternative (lean, gallery or reference, exactly as the facts rank them), why (one sentence).
  3. jobs - seven objects in this order: job (evaluate, first-call, workflow, production, start, mobile, agent), artifact (the artifact type serving it), languages (short strings), served (true or false), condition (one sentence when not served: what would add it; empty when served).
  4. coverage - flagship_languages (exactly the tier-1 set), scenario_languages (two or three of the dominant languages).
  5. freshness - ci, credentials, dependencies, sla, pins (one sentence each - the five terms of the contract; the SLA names its days).
  6. archive_rules - short strings: the evidence triggers and the archive sequence; never age alone.
  7. index - one sentence: the one canonical index and the surfaces it drives.
  8. measurement - short strings: the sample-ID tag and the signals; stars and forks never decide.
  9. caveats - at most 4 short strings; [] when there is nothing to say.
{
  "task": "strategy",
  "summary": "one sentence",
  "shape": { "recommended": "lean", "alternative": "gallery", "why": "one sentence" },
  "jobs": [ { "job": "evaluate", "artifact": "hosted collection", "languages": [ ], "served": true, "condition": "" } ],
  "coverage": { "flagship_languages": [ "node" ], "scenario_languages": [ "node" ] },
  "freshness": { "ci": "one sentence", "credentials": "one sentence", "dependencies": "one sentence", "sla": "one sentence", "pins": "one sentence" },
  "archive_rules": [ "a short string" ],
  "index": "one sentence",
  "measurement": [ "a short string" ],
  "caveats": [ ]
}

The page holds it to its own facts (check() in streply.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 ranked shape; the seven jobs in order, each served with an artifact or not served with a condition; the tier-1 set as the flagship languages and two or three dominant scenario languages; all five freshness terms, CI against the sandbox (or compiled, not run without one), an SLA in days; at least four archive triggers and none on age alone; one canonical index; sample-ID measurement with stars and forks never deciding.

cleanup

Write the cleanup plan for every row the page did not simply keep.

  1. summary - one sentence, at most 40 words.
  2. rows - one object per row the register does not keep, in its order: repo (as written), verdict (secure, archive, community, fix, rebuild or merge, exactly as the register reads it), successor (exactly as the register gives it; empty for fix and rebuild), action (one sentence: what happens - a secure row is fixed or archived this week; a fix names who owns it, escalated when nobody does), banner (for archive, merge and community: the README banner text naming the successor, or that there is none; empty otherwise), notify (who to tell first when the row is linked from sales or partner material; empty otherwise).
  3. sequence - short strings in order: scans first, then archives and merges, then adoption-path fixes before the deadline.
  4. caveats - at most 4 short strings; [] when there is nothing to say.
{
  "task": "cleanup",
  "summary": "one sentence",
  "rows": [ { "repo": "checkout-legacy", "verdict": "archive", "successor": "checkout-starter", "action": "one sentence", "banner": "a short string", "notify": "" } ],
  "sequence": [ "a short string" ],
  "caveats": [ ]
}

The page requires: the reply answers the task it was sent; the same text rules; exactly the page's non-kept rows in order with its verdicts and successors; a banner on every archive, merge and community row; no deletion; a scan hit handled this week; the owner of a sales or partner link told first; an action each; a sequence that starts with the scans.

Worked examples

Three runs from the page's free samples (invented platforms): the strategy for a payments samples org over capacity, the cleanup for the same org carrying that strategy, and the strategy for an infrastructure portfolio close to green. 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.

strategy - A payments samples org over capacity

The page read it as: a secret or vulnerability first; shape lean; 93 upkeep hours a quarter kept against 60; repos: accept-a-payment (keep), pennaroo-quickstart-php (archive), samples/subscriptions (keep), samples/disputes (archive), refunds-standalone (merge), webhook-relay (secure), checkout-legacy (archive), checkout-starter (keep), dashboard-demo (archive), payouts-reference (keep), ios-card-payments (keep), pennaroo-postman (keep); 3 of 5 gates; failing checks: secrets, capacity.

Input (register is 2666 characters; the first 1399 are shown; facts is 1873 characters; the first 1397 are shown):

{
 "task": "strategy",
 "platform": "Platform: Pennaroo\nWho integrates and what samples exist: A payments API; merchants' backend developers integrate checkout, subscriptions and payouts, and mobile apps take card payments in-app. The samples org has grown to twelve repos.\nKind: Payments or fintech; SDK tier-1 languages: Node, Python, Ruby, Java, Go; languages API traffic shows dominate: Node, Python; mobile SDK tier 1: yes\nCI can run against: A sandbox or test mode with test keys; usage signal: CLI or deploy-button invocations; retired SDK majors or API versions: sdk v2\nUpkeep hours a quarter: 60; one-off cleanup hours: 80; red-build SLA days: 7; a regulated or multi-service flow drives deals: no\nDeadline near: no; a standing quarterly policy; as-of: 2026-11-01",
 "register": "Register in the order given (repo | type | job | languages | pins | owner | CI | usage | tickets | links | verdict):\n- accept-a-payment | flagship | first-call | node, python, ruby, java, go | pins sdk v5 | owner Ana Ruiz | CI green | usage 4200 | 3 tickets | links docs | KEEP: on the adoption path - green | 15 h/quarter\n- pennaroo-quickstart-php | quickstart | first-call | php | pins sdk v5 | owner none | CI red | usage 120 | 2 tickets | links docs | ARCHIVE -> accept-a-payment: php is outside the coverage\n- samples/subscriptions | scenario | workflow | node, python | pins sdk v5 | owner Jo Mensah | CI green | usage 800 | 9 tickets | links docs | KEEP: on the adoption path - green | 8 h/quarter\n- samples/disputes | scenario | workflow | ruby | pins sdk v5 | owner Kim Park | CI red | usage 3 | 0 tickets | links none | ARCHIVE -> samples/subscriptions: ruby is outside the coverage\n- refunds-standalone | scenario | workflow | python | pins sdk v5 | owner Lee Chan | CI green | usage 300 | 1 ticket | links docs | MERGE -> the shared samples repo: a single-concern scenario in its own repo - one CI pipeline replaces many\n- webhook-relay | scenario | workflow | node | pins sdk v5 | owner Lee Chan | CI green | usage 200 | 0 tickets | links docs | SCAN HIT | SECURE: a secret or vulnerable-dependency hit overrides every other verdict\n- checkout-legacy | template | start | node | pins sdk\n\n[... 1267 more characters cut from this display ...]",
 "carry": "",
 "facts": "The page's checks (2 fail, 2 warn, 4 pass, 1 n/a); verdict: a secret or vulnerability first:\n- The register | owners | pass | 6 kept artifacts, each with a named person\n- The register | secrets | fail | webhook-relay - fix or archive this week, before any other verdict\n- Coverage and capacity | capacity | fail | 93 hours a quarter kept (self-set estimates) against 60 - cut languages within a job first, then step down to the default artifact, then across jobs from the bottom of the efficiency line\n- Coverage and capacity | shape | na | Lean golden path first, gallery-led as the alternative\n- Coverage and capacity | jobs | warn | served: evaluate, first-call, workflow, production, start, mobile; not served: agent - say so with the condition that would add it\n- Freshness and archives | ci | pass | A sandbox or test mode with test keys\n- Freshness and archives | sla | pass | fix-or-deprecate decision after 7 days (self-set)\n- Freshness and archives | successors | pass | pennaroo-quickstart-php -> accept-a-payment; samples/disputes -> samples/subscriptions; refunds-standalone -> the shared samples repo; checkout-legacy -> checkout-starter; dashboard-demo -> checkout-starter\n- Freshness and archives | links | warn | checkout-legacy - notify that owner and swap the link first\nShapes by the skill's ranking, in order: lean, gallery, reference.\nmust: shape recommended lean, alternative\n\n[... 476 more characters cut from this display ...]"
}

Reply:

{
 "task": "strategy",
 "summary": "Lean golden path: step the Java payouts reference app down to a docs architecture page plus scenarios, bringing 93 self-set hours toward 53 against 60, after webhook-relay's scan hit is fixed or archived this week.",
 "shape": {
  "recommended": "lean",
  "alternative": "gallery",
  "why": "No regulated or multi-service flow drives deals, so one flagship quickstart at tier-1 parity plus scenarios in the shared repo serves the jobs within the quarter's hours."
 },
 "jobs": [
  {
   "job": "evaluate",
   "artifact": "hosted collection (pennaroo-postman)",
   "languages": [],
   "served": true,
   "condition": ""
  },
  {
   "job": "first-call",
   "artifact": "flagship multi-language quickstart (accept-a-payment)",
   "languages": [
    "node",
    "python",
    "ruby",
    "java",
    "go"
   ],
   "served": true,
   "condition": ""
  },
  {
   "job": "workflow",
   "artifact": "scenario samples in the shared repo (samples/subscriptions, refunds merged in)",
   "languages": [
    "node",
    "python"
   ],
   "served": true,
   "condition": ""
  },
  {
   "job": "production",
   "artifact": "docs architecture page plus scenarios, stepped down from payouts-reference to fit capacity",
   "languages": [
    "node",
    "python"
   ],
   "served": true,
   "condition": ""
  },
  {
   "job": "start",
   "artifact": "starter template with a deploy button (checkout-starter)",
   "languages": [
    "node"
   ],
   "served": true,
   "condition": ""
  },
  {
   "job": "mobile",
   "artifact": "one app per platform (ios-card-payments)",
   "languages": [
    "swift"
   ],
   "served": true,
   "condition": ""
  },
  {
   "job": "agent",
   "artifact": "canonical index plus an agent guide",
   "languages": [],
   "served": false,
   "condition": "Publish the canonical index with an agent guide once tagged traffic shows coding agents making first calls and the hours freed by the step-down cover it."
  }
 ],
 "coverage": {
  "flagship_languages": [
   "node",
   "python",
   "ruby",
   "java",
   "go"
  ],
  "scenario_languages": [
   "node",
   "python"
  ]
 },
 "freshness": {
  "ci": "Every kept artifact runs scheduled CI against the sandbox with test keys, plus a run on every SDK release and API version change.",
  "credentials": "CI uses scoped sandbox-only test keys, never exposed to fork pull requests and rotated on a schedule.",
  "dependencies": "Dependency updates arrive grouped on a throttled cadence, while security alerts are handled outside that cadence.",
  "sla": "A red build opens an owner ticket on the first red run and forces a fix-or-deprecate decision after 7 days (self-set).",
  "pins": "Every artifact pins a supported SDK major (sdk v5), runtime and API version, and nothing pins the retired sdk v2."
 },
 "archive_rules": [
  "Red past the 7-day SLA",
  "No owner for one review cycle, outside the adoption path",
  "Superseded by a successor",
  "Pins an end-of-life SDK or API version, such as sdk v2",
  "Low measured usage and red together; unmeasured usage is never read as zero",
  "Never archive on age alone",
  "Sequence: swap any sales or partner link, README banner with successor link, redirect in the canonical index, last secret scan, bots and CI stopped, then read-only",
  "Never delete"
 ],
 "index": "One machine-readable canonical index drives the docs, the gallery, the scaffold CLI, GitHub topics and the agent index.",
 "measurement": [
  "Tag API traffic with the sample ID",
  "Invocations per sample (CLI and deploy-button)",
  "Time to first call",
  "Tickets per sample",
  "CI pass rate",
  "Stars and forks are vanity and never decide"
 ],
 "caveats": [
  "Upkeep hours are self-set per-type estimates, not measured.",
  "Stepping down payouts-reference frees 40 self-set hours; swap its partner link first.",
  "payouts-reference usage is not measured, so it is never read as zero.",
  "checkout-legacy sits in a sales deck; notify that owner and swap the link before archiving."
 ]
}

What step 5 prints for it: evaluate served | first-call served | workflow served | production served | start served | mobile served | agent not served

The page's check: kept - nothing to flag

cleanup - A payments samples org over capacity

The input carries the saved strategy's decisions (R.laneForm fills carry from the strategy reply), as the page's handoff does. The rows to change: pennaroo-quickstart-php (archive), samples/disputes (archive), refunds-standalone (merge), webhook-relay (secure), checkout-legacy (archive), dashboard-demo (archive).

Input (register is 2666 characters; the first 1399 are shown; facts is 1850 characters; the first 1380 are shown):

{
 "task": "cleanup",
 "platform": "Platform: Pennaroo\nWho integrates and what samples exist: A payments API; merchants' backend developers integrate checkout, subscriptions and payouts, and mobile apps take card payments in-app. The samples org has grown to twelve repos.\nKind: Payments or fintech; SDK tier-1 languages: Node, Python, Ruby, Java, Go; languages API traffic shows dominate: Node, Python; mobile SDK tier 1: yes\nCI can run against: A sandbox or test mode with test keys; usage signal: CLI or deploy-button invocations; retired SDK majors or API versions: sdk v2\nUpkeep hours a quarter: 60; one-off cleanup hours: 80; red-build SLA days: 7; a regulated or multi-service flow drives deals: no\nDeadline near: no; a standing quarterly policy; as-of: 2026-11-01",
 "register": "Register in the order given (repo | type | job | languages | pins | owner | CI | usage | tickets | links | verdict):\n- accept-a-payment | flagship | first-call | node, python, ruby, java, go | pins sdk v5 | owner Ana Ruiz | CI green | usage 4200 | 3 tickets | links docs | KEEP: on the adoption path - green | 15 h/quarter\n- pennaroo-quickstart-php | quickstart | first-call | php | pins sdk v5 | owner none | CI red | usage 120 | 2 tickets | links docs | ARCHIVE -> accept-a-payment: php is outside the coverage\n- samples/subscriptions | scenario | workflow | node, python | pins sdk v5 | owner Jo Mensah | CI green | usage 800 | 9 tickets | links docs | KEEP: on the adoption path - green | 8 h/quarter\n- samples/disputes | scenario | workflow | ruby | pins sdk v5 | owner Kim Park | CI red | usage 3 | 0 tickets | links none | ARCHIVE -> samples/subscriptions: ruby is outside the coverage\n- refunds-standalone | scenario | workflow | python | pins sdk v5 | owner Lee Chan | CI green | usage 300 | 1 ticket | links docs | MERGE -> the shared samples repo: a single-concern scenario in its own repo - one CI pipeline replaces many\n- webhook-relay | scenario | workflow | node | pins sdk v5 | owner Lee Chan | CI green | usage 200 | 0 tickets | links docs | SCAN HIT | SECURE: a secret or vulnerable-dependency hit overrides every other verdict\n- checkout-legacy | template | start | node | pins sdk\n\n[... 1267 more characters cut from this display ...]",
 "carry": "Shape: lean\nJobs: evaluate - hosted collection (pennaroo-postman); first-call - flagship multi-language quickstart (accept-a-payment); workflow - scenario samples in the shared repo (samples/subscriptions, refunds merged in); production - docs architecture page plus scenarios, stepped down from payouts-reference to fit capacity; start - starter template with a deploy button (checkout-starter); mobile - one app per platform (ios-card-payments); agent - not served\nCoverage: flagship node, python, ruby, java, go; scenarios node, python\nFreshness: Every kept artifact runs scheduled CI against the sandbox with test keys, plus a run on every SDK release and API version change. / A red build opens an owner ticket on the first red run and forces a fix-or-deprecate decision after 7 days (self-set).\nIndex: One machine-readable canonical index drives the docs, the gallery, the scaffold CLI, GitHub topics and the agent index.",
 "facts": "The page's checks (2 fail, 2 warn, 4 pass, 1 n/a); verdict: a secret or vulnerability first:\n- The register | owners | pass | 6 kept artifacts, each with a named person\n- The register | secrets | fail | webhook-relay - fix or archive this week, before any other verdict\n- Coverage and capacity | capacity | fail | 93 hours a quarter kept (self-set estimates) against 60 - cut languages within a job first, then step down to the default artifact, then across jobs from the bottom of the efficiency line\n- Coverage and capacity | shape | na | Lean golden path first, gallery-led as the alternative\n- Coverage and capacity | jobs | warn | served: evaluate, first-call, workflow, production, start, mobile; not served: agent - say so with the condition that would add it\n- Freshness and archives | ci | pass | A sandbox or test mode with test keys\n- Freshness and archives | sla | pass | fix-or-deprecate decision after 7 days (self-set)\n- Freshness and archives | successors | pass | pennaroo-quickstart-php -> accept-a-payment; samples/disputes -> samples/subscriptions; refunds-standalone -> the shared samples repo; checkout-legacy -> checkout-starter; dashboard-demo -> checkout-starter\n- Freshness and archives | links | warn | checkout-legacy - notify that owner and swap the link first\nShapes by the skill's ranking, in order: lean, gallery, reference.\nmust: rows lists exactly\n\n[... 470 more characters cut from this display ...]"
}

Reply:

{
 "task": "cleanup",
 "summary": "Secure webhook-relay this week, then archive four repos and merge refunds-standalone into the shared samples repo, swapping the checkout-legacy sales deck link first; nothing is deleted.",
 "rows": [
  {
   "repo": "pennaroo-quickstart-php",
   "verdict": "archive",
   "successor": "accept-a-payment",
   "action": "Archive it because php sits outside the coverage: add the banner and successor link, redirect it in the canonical index to accept-a-payment, run a last secret scan, stop bots and CI, then set it read-only and never delete it.",
   "banner": "Archived: PHP is outside Pennaroo's supported languages. Use accept-a-payment, the flagship quickstart, instead.",
   "notify": ""
  },
  {
   "repo": "samples/disputes",
   "verdict": "archive",
   "successor": "samples/subscriptions",
   "action": "Kim Park archives it because ruby sits outside the scenario coverage: banner and successor link, a redirect in the canonical index to samples/subscriptions, a last secret scan, bots and CI stopped, then read-only, never deleted.",
   "banner": "Archived: Ruby scenarios are no longer maintained. See samples/subscriptions for the maintained workflow samples.",
   "notify": ""
  },
  {
   "repo": "refunds-standalone",
   "verdict": "merge",
   "successor": "the shared samples repo",
   "action": "Lee Chan moves the refunds scenario into the shared samples repo under its single CI pipeline, then this repo gets the banner, a redirect in the canonical index, a last secret scan, bots and CI stopped, then goes read-only, never deleted.",
   "banner": "Moved: this refunds sample now lives in the shared samples repo. This copy is read-only.",
   "notify": ""
  },
  {
   "repo": "webhook-relay",
   "verdict": "secure",
   "successor": "",
   "action": "Lee Chan fixes the scan hit this week by rotating the exposed credential or patching the vulnerable dependency and re-running the secret scan, or archives the repo this week if the fix cannot land.",
   "banner": "",
   "notify": ""
  },
  {
   "repo": "checkout-legacy",
   "verdict": "archive",
   "successor": "checkout-starter",
   "action": "Once the sales deck points at checkout-starter, Sam Ito archives it for pinning the retired sdk v2: banner and successor link, a redirect in the canonical index, a last secret scan, bots and CI stopped, then read-only, never deleted.",
   "banner": "Archived: this template pins the retired SDK v2. Start from checkout-starter instead.",
   "notify": "Tell Sam Ito first and swap the sales deck link to checkout-starter before archiving."
  },
  {
   "repo": "dashboard-demo",
   "verdict": "archive",
   "successor": "checkout-starter",
   "action": "Archive it because no named owner accepted it: banner and successor link, a redirect in the canonical index to checkout-starter, a last secret scan, bots and CI stopped, then read-only, never deleted.",
   "banner": "Archived: this demo has no maintainer. Start from checkout-starter instead.",
   "notify": ""
  }
 ],
 "sequence": [
  "Secure webhook-relay this week and run a last secret scan on every repo about to be archived or merged.",
  "Swap the checkout-legacy sales deck link to checkout-starter.",
  "Archive pennaroo-quickstart-php, samples/disputes, checkout-legacy and dashboard-demo, and merge refunds-standalone into the shared samples repo.",
  "No adoption-path fix is open; payouts-reference stays kept while red, with an owner ticket for Mo Haddad under the 7-day SLA."
 ],
 "caveats": [
  "Kept upkeep is 93 hours a quarter against 60, so the cleanup alone does not close the capacity gap.",
  "payouts-reference usage is not measured, which is never read as zero.",
  "Upkeep hours are self-set estimates."
 ]
}

What step 5 prints for it: pennaroo-quickstart-php archive | samples/disputes archive | refunds-standalone merge | webhook-relay secure | checkout-legacy archive | dashboard-demo archive

The page's check: kept - nothing to flag

strategy - An infrastructure portfolio close to green

The page read it as: a portfolio the team can keep green; shape lean; 18 upkeep hours a quarter kept against 40; repos: grindleaf-quickstart (keep), samples/networks (keep), samples/networks-copy (merge), grindleaf-starter (keep), terraform-demo-2024 (archive); 5 of 5 gates; failing checks: none.

Input (facts is 1564 characters; the first 1396 are shown):

{
 "task": "strategy",
 "platform": "Platform: Grindleaf\nWho integrates and what samples exist: An infrastructure provisioning API; platform engineers start from a starter template and the Go quickstart.\nKind: Infrastructure; SDK tier-1 languages: Go, Python; languages API traffic shows dominate: Go, Python; mobile SDK tier 1: no\nCI can run against: A sandbox or test mode with test keys; usage signal: CLI or deploy-button invocations; retired SDK majors or API versions: api 2024-01\nUpkeep hours a quarter: 40; one-off cleanup hours: 20; red-build SLA days: 5; a regulated or multi-service flow drives deals: no\nDeadline near: no; a standing quarterly policy; as-of: 2026-11-01",
 "register": "Register in the order given (repo | type | job | languages | pins | owner | CI | usage | tickets | links | verdict):\n- grindleaf-quickstart | flagship | first-call | go, python | pins api 2026-03 | owner Nia Cole | CI green | usage 2100 | 1 ticket | links docs | KEEP: on the adoption path - green | 6 h/quarter\n- samples/networks | scenario | workflow | go | pins api 2026-03 | owner Bo Lind | CI green | usage 400 | 3 tickets | links docs | KEEP: on the adoption path - green | 4 h/quarter\n- samples/networks-copy | scenario | workflow | go | pins api 2026-03 | owner Bo Lind | CI green | usage 30 | 0 tickets | links none | MERGE -> samples/networks: duplicates samples/networks for the same job and languages\n- grindleaf-starter | template | start | go | pins api 2026-03 | owner Nia Cole | CI green | usage 700 | 0 tickets | links docs | KEEP: green | 8 h/quarter\n- terraform-demo-2024 | template | start | go | pins api 2024-01 | owner Bo Lind | CI red | usage 20 | 0 tickets | links partner | ARCHIVE -> grindleaf-starter: pins a retired SDK major or API version (api 2024-01)\nKept upkeep: 18 hours a quarter against 40 (self-set per-type estimates: reference 40, mobile 20, playground 20, flagship 3 per language, template 8 per language, scenario 4 per language, quickstart 2 per language, collection 2).",
 "carry": "",
 "facts": "The page's checks (0 fail, 2 warn, 6 pass, 1 n/a); verdict: a portfolio the team can keep green:\n- The register | owners | pass | 3 kept artifacts, each with a named person\n- The register | secrets | pass | every repo scanned clean\n- Coverage and capacity | capacity | pass | 18 hours a quarter kept (self-set estimates) against 40\n- Coverage and capacity | shape | na | Lean golden path first, gallery-led as the alternative\n- Coverage and capacity | jobs | warn | served: first-call, workflow, start; not served: evaluate, production, mobile, agent - say so with the condition that would add it\n- Freshness and archives | ci | pass | A sandbox or test mode with test keys\n- Freshness and archives | sla | pass | fix-or-deprecate decision after 5 days (self-set)\n- Freshness and archives | successors | pass | samples/networks-copy -> samples/networks; terraform-demo-2024 -> grindleaf-starter\n- Freshness and archives | links | warn | terraform-demo-2024 - notify that owner and swap the link first\nShapes by the skill's ranking, in order: lean, gallery, reference.\nmust: shape recommended lean, alternative gallery; jobs lists the seven jobs in this order: evaluate, first-call, workflow, production, start, mobile, agent, each served or not served with the condition that would add it; flagship languages go, python; scenario languages two or three of go, python; the freshness contract's five\n\n[... 168 more characters cut from this display ...]"
}

Reply:

{
 "task": "strategy",
 "summary": "Lean golden path at 18 of 40 self-set hours, nothing to cut; the first blocker is terraform-demo-2024, whose partner link must be swapped before it is archived to grindleaf-starter.",
 "shape": {
  "recommended": "lean",
  "alternative": "gallery",
  "why": "Platform engineers start from the Go quickstart and a starter template, and no regulated or multi-service flow drives deals, so a flagship plus shared scenarios fits."
 },
 "jobs": [
  {
   "job": "evaluate",
   "artifact": "hosted collection",
   "languages": [],
   "served": false,
   "condition": "Add a hosted collection against the sandbox once tagged traffic shows engineers evaluating before they install."
  },
  {
   "job": "first-call",
   "artifact": "flagship multi-language quickstart (grindleaf-quickstart)",
   "languages": [
    "go",
    "python"
   ],
   "served": true,
   "condition": ""
  },
  {
   "job": "workflow",
   "artifact": "scenario samples in the shared repo (samples/networks, copy merged in)",
   "languages": [
    "go"
   ],
   "served": true,
   "condition": ""
  },
  {
   "job": "production",
   "artifact": "docs architecture page plus scenarios",
   "languages": [],
   "served": false,
   "condition": "Add a docs architecture page backed by the shared scenarios once tickets or tagged traffic show engineers asking for the production pattern."
  },
  {
   "job": "start",
   "artifact": "starter template with a deploy button (grindleaf-starter)",
   "languages": [
    "go"
   ],
   "served": true,
   "condition": ""
  },
  {
   "job": "mobile",
   "artifact": "one app per platform",
   "languages": [],
   "served": false,
   "condition": "Add one app per platform only when the mobile SDK reaches tier 1."
  },
  {
   "job": "agent",
   "artifact": "canonical index plus an agent guide",
   "languages": [],
   "served": false,
   "condition": "Publish the canonical index with an agent guide once tagged traffic shows coding agents making first calls."
  }
 ],
 "coverage": {
  "flagship_languages": [
   "go",
   "python"
  ],
  "scenario_languages": [
   "go",
   "python"
  ]
 },
 "freshness": {
  "ci": "Every kept artifact runs scheduled CI against the sandbox with test keys, plus a run on every SDK release and API version change.",
  "credentials": "CI uses scoped sandbox-only test keys, never exposed to fork pull requests and rotated on a schedule.",
  "dependencies": "Dependency updates arrive grouped on a throttled cadence, while security alerts are handled outside that cadence.",
  "sla": "A red build opens an owner ticket on the first red run and forces a fix-or-deprecate decision after 5 days (self-set).",
  "pins": "Every artifact pins a supported SDK, runtime and API version (api 2026-03), and nothing pins the retired api 2024-01."
 },
 "archive_rules": [
  "Red past the 5-day SLA",
  "No owner for one review cycle, outside the adoption path",
  "Superseded or duplicated by a survivor",
  "Pins an end-of-life SDK or API version, such as api 2024-01",
  "Low measured usage and red together; unmeasured usage is never read as zero",
  "Never archive on age alone",
  "Sequence: swap any sales or partner link, README banner with successor link, redirect in the canonical index, last secret scan, bots and CI stopped, then read-only",
  "Never delete"
 ],
 "index": "One machine-readable canonical index drives the docs, the gallery, the scaffold CLI, GitHub topics and the agent index.",
 "measurement": [
  "Tag API traffic with the sample ID",
  "Invocations per sample (CLI and deploy-button)",
  "Time to first call",
  "Tickets per sample",
  "CI pass rate",
  "Stars and forks are vanity and never decide"
 ],
 "caveats": [
  "Upkeep hours are self-set per-type estimates, not measured.",
  "Scenario samples ship in Go only today; Python is the second dominant language to add within the spare hours.",
  "terraform-demo-2024 sits in partner material; notify that owner and swap the link before archiving."
 ]
}

What step 5 prints for it: evaluate not served | first-call served | workflow served | production not served | start served | mobile not served | agent not served

The page's check: kept - nothing to flag

Build the input yourself

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

const K = SampleKit, R = SampleReply;
const f = K.form(Object.assign(K.blank(), { name: "Acme", tier1: "Node, Python", toplangs: "Node", retired: "sdk v1", hours: "40", sandbox: "sandbox",
  register: "quickstart | quickstart | first call | Node | sdk v3 | Ann | green | 900 | 2 | docs | clean\nold-demo | template | start | Node | sdk v1 | Bo | red | 10 | 0 | sales | clean" }));
// f.regRows (each repo with its verdict, why, successor and upkeep), f.need, f.rank (the ranked shapes), f.gate
// K.registerMd(f), K.indexJson(f) - the register table and the canonical index
const b = K.buildInput(f, "strategy");                       // or "cleanup" (R.laneForm(form, "cleanup", strategy) fills carry)
const wire = K.toWire(b.input);                              // POST this to /estimate and /run
// then: const reply = R.normalize(R.parseReply(job.output.output), "strategy");
// 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://sample-triage.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":"sample-triage"}' | 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": "strategy", "platform": "Platform: Pennaroo
Who integrates and what samples exist: ...", "register": "Register in the order given (repo | type | job | ...):
- accept-a-payment | flagship | first-call | ... | KEEP: ...", "carry": "", "facts": "The page's checks (...); verdict: a secret or vulnerability first:
- The register | owners | pass | ..."}
# - 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 sample-triage:<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 strategy reply carries summary, shape, jobs, coverage, freshness, archive_rules, index, measurement and caveats; a cleanup reply carries summary, rows, sequence and caveats. The code below prints the gist of either: each job and whether it is served, or each row and its verdict.

KEY="sample-triage:$(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 == "cleanup" then (.rows[] | "\(.repo): \(.verdict)") 
       else (.jobs[] | "\(.job): \(.served)") 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: sample-triage:$(jq -r .task input.json):$(shasum -a 256 input.json | cut -c1-16):a1" --data @input.json