name: belz-ai description: Belzabar tooling primer + per-task workflow. ALWAYS load this skill at the start of any session in this directory — it explains what belz / AD / PD / Teamwork are and enforces the per-task subdirectory + TASK.md workflow. Also triggers on Teamwork URLs (projects.webintensive.com/app/tasks/...), task codes like NCNSS-XXX, "start task" / "new task", or any question about belz, AD chains, PD pages, NSM environments, or fetching task metadata.
Belzabar Workflow Skill
You are working on belzabar — an internal developer toolset for the user's NSM platform team. This skill loads two things into context:
- A primer on what belzabar is and how to think about its CLI (
belz). - A strict per-task workflow for organizing scratch work in subdirectories with a
TASK.mdlog.
This skill is not a command reference. For exact flags, always run belz --help-full or belz <ns> <cmd> --help. Never invent commands or flags from memory.
If the user's task involves NSM domain concepts (LT-260, LT-262, "Vehicle Sold", chain IDs, etc.), the nsm skill carries that knowledge. It is opt-in — the user invokes it with /nsm when they want that context loaded. If the user mentions an NSM concept and the nsm skill isn't loaded, say so rather than guess.
Step 0 — Mandatory session bootstrap
Before doing anything else in a new session, run:
belz --help-full
This dumps the complete, current command reference (union of every desc.txt in the repo). It is the source of truth for what belz can do. Read it before suggesting any command. If belz --help-full fails (binary not installed, PATH issue), stop and tell the user — do not try to work around it.
Run this once per session, early. You don't need to re-run it unless the user says they just rebuilt belz.
Part 1 — Belzabar Primer
What belzabar is
Belzabar is the toolset the user's team uses to work on NSM (and similar Verifi-hosted apps). It ships three things; the CLI is the one that matters for daily work:
belzCLI — unified binary, the source of truth for everything below.- Browser extension — content script that enhances the AD/PD web UIs (e.g.
Ctrl+Shift+Enterto run a test). - Web app at
web/— AI-driven session UI for pasting curl commands and managing agents.
The CLI wraps three otherwise-painful systems: Automation Designer, Page Designer, and Teamwork.
Automation Designer (AD)
AD is the backend platform. Business logic lives there as chains of step-by-step services — think of a chain as a stored-procedure-as-a-graph.
Key vocabulary:
- Method / chain — one named unit (e.g.
LT260.submit). Has a UUID ("published id"), inputs, and an ordered list of steps. - Step — a single operation in the chain. Can be SQL, code (SpEL or JS), an HTTP call, or a sub-method invocation. Steps can have conditions, loops, and error handling.
- Service category — top-level grouping. Common ones for NSM:
NSM.Staff,NSM.Public,NSM.Helpers,NSM.Reporting,NSM.Templates. - Published ID — the UUID at the end of an AD URL like
https://nsm-dev.nc.verifi.dev/automation-designer/NSM.Staff/abc123def456. This is whatbelz ad showand Dev Notes consume.
Daily AD operations (use --help for flags):
belz ad find— search/list methods by namebelz ad show <uuid>— fetch and display a method (--fullfor steps + services)belz ad test <uuid>— run a draft with a JSON input, get per-step tracebelz ad run <uuid>— execute the published method live (--streamto opt into a streaming method —application/stream+jsonchunks + a final JSON envelope)belz ad publish <uuid> --note "<what changed>"— promote a draft to published.--noteis mandatory; belz records it to the chain's changelog before publishing.belz ad changelog <uuid>— list a method's change notes;--note "<text>"records one without publishingbelz ad sql tui— interactive SQL session against AD's DB accounts
Writing changelog notes. Keep every note short and literal — one line that says which step(s) changed and how, using plain verbs: created / added / updated / removed / deleted. Name the step. No narration, no padding.
Step 3.2: condition now also allows CANCELLEDAdded step 4 (SQL update on application); removed old step 6Updated LT260.submit output mapping for case_number
One note per logical change. Run belz ad changelog <uuid> first and don't
restate something already recorded. belz ad publish always requires a
--note, so a minor follow-up re-publish of a change you just logged (a typo or
small tweak) doesn't deserve a fresh full entry — keep that note terse and
pointing at the original instead of duplicating it.
Methods are cached at ~/.belz/cache/methods/<uuid>.json for 5 minutes — pass --force to bypass.
Page Designer (PD)
PD is the frontend platform. Pages are configured as JSON: variables, derived expressions, HTTP service calls (which usually invoke AD methods), and a tree of components.
Key vocabulary:
- Page — a top-level container with its own hex ID. Maps to a route like
/ncdot-notice-and-storage/lt-260-submission. - Component — a reusable UI piece a page (or another component) embeds.
- Variable — page-level state. Can be user-defined or derived (computed from an expression).
- HTTP call — a service binding that hits an AD method endpoint.
Daily PD operations:
belz pd show <input>— overview of a page or component.<input>accepts an app URL, a PD designer URL, a bare hex ID, or a component name.belz pd show <input> --vars/--http/--components/--fullbelz pd find [query]— search the page index (cached 7 days)belz pd find-ad-methods <id> --recursive— extract every AD method ID a page (and its component tree) depends on. Use this when a frontend bug is actually a backend one.belz pd validate <input>— run the 10 standard validation checksbelz pd analyze [PAGE_ID]— recursive dependency + compliance analysisbelz pd diff <input> --from <envA> --to <envB>— structural diff of the same page/component across two environments (variables, derived, HTTP, nodes, styles)
Teamwork
The team tracks work in Teamwork at projects.webintensive.com. The CLI:
belz tw task <id|url>— fetch title, tags, status, workflow stage, description, comment countbelz tw comments <id|url>— fetch commentsbelz tw search <query>— search tasks by keyword (read-only)belz tw add-comment <id|url> --body "<text>"— post a comment (WRITE — gated, see below)
Auth is cookie-based, separate from the NSM Bearer-token flow. Sessions live at ~/.belz/sessions/teamwork.json.
Posting comments — strict rule. belz tw add-comment writes to Teamwork.
Never post a comment without first showing the user the exact comment text
and getting their explicit validation in the chat — every single time, even
if the user told you to "go ahead" earlier. A prior go-ahead never carries over
to a new comment or a reworded one. Re-show the exact text and re-confirm before
each post; only then run the command with --yes. The command refuses in
--llm mode without --yes precisely so this can't happen by accident.
Migrations and environments
belz migrate profiles— list available migration profilesbelz migrate run --module PD --ids "<id>" --source-env nsm-dev --target-env nsm-qa— promote a chain / page / component between environmentsbelz migrate status <build#>/belz migrate logs <build#>— inspect a buildbelz envs— list configured environments
belz migrate run accepts either a draft or published id — you don't need to
look up the published id yourself. Migrations ultimately run on published ids
(the migration service 500s on a raw draft id, while Jenkins misleadingly still
prints "SUCCESS"), but belz migrate run handles that: it resolves every id
against the source environment first and auto-swaps a PD draft for its published
sibling (showing the entity name). PD ids are environment-local, so this
resolution also catches an id that doesn't exist on the source.
Always pass the source environment's id — never the destination env's. PD
items (pages and components) get re-imported on each environment, so the same
logical page has a different (draftId, publishedId) pair on dev, qa, uat,
stage, and prod. The migration service expects the id as it exists on
--source-env; it takes the bytes from there and writes a new
(potentially-different) id on --target-env. If you accidentally pass the
target env's id, the source lookup either 404s or — worse — silently resolves
to a different page that happens to share that hex on the source, and you ship
the wrong content. AD chain UUIDs are stable across envs, so this caveat is a
PD problem specifically — but the rule "pass the id as it exists on
--source-env" applies uniformly to both modules.
Default environment is nsm-dev. Override per-command with --env nsm-qa (etc.).
The --llm flag
Every command takes --llm to emit a deterministic JSON envelope:
{ "schema": "...", "version": "2.0", "ok": true, "command": "...", "data": {...}, "error": null, "meta": {} }
Always pass --llm when you (the agent) invoke belz programmatically. Human mode is for humans only — it produces tables that are noisy to parse.
Where things live on disk
Everything under ~/.belz/:
| Path | Contents |
|---|---|
config.json |
Credentials (file wins over env vars) |
sessions/<env>.json |
Auth sessions per environment |
sessions/teamwork.json |
Teamwork cookie session |
cache/methods/<uuid>.json |
AD method cache (5-min TTL) |
cache/definitions/<id>.json |
AD chain body cache |
cache/method-finder/index-v1-<env>.json |
Method finder index (7-day TTL) |
migrations/nsm-profiles.json |
Migration profile cache |
Companion skills
tw-dev-note— generates standardized Dev Notes (NDNs) for Teamwork comments. Defer to it whenever the user says "NDN", "Dev Note", or asks to format finished AD/PD changes for handoff. Do not format Dev Notes by hand.nsm-context— domain knowledge for the NSM project (forms, statuses, chain IDs, lifecycle paths). Loads on NSM-related triggers.
Hard rules for using belz
- Never invent flags. Run
belz --help-fullorbelz <ns> <cmd> --helpfirst. - Always pass
--llmwhen invoking from a tool call so output is parseable. - Don't memorize chain IDs, page IDs, or method names — fetch them with
belzon demand. - Cached results may be up to 5 minutes stale. Pass
--forceif the user just edited a method. - Publishing an AD method always needs a change note:
belz ad publishrequires--note "<what changed>"and logs it to the changelog. Never work around this — the note is the audit trail. Keep the note short and literal (which step changed + how) and don't duplicate a note already in the changelog — see "Writing changelog notes". - Never post a Teamwork comment (
belz tw add-comment) without first showing the user the exact comment text and getting their explicit validation in chat — every time, even if they approved posting earlier. A prior go-ahead never carries over.
Part 2 — Per-Task Workflow
Follow this workflow exactly when doing any work in this directory. Do not skip steps or improvise.
There are two modes:
- Task mode — the user shared a Teamwork link or task code. Fetch metadata, create a
<CODE>/subdir, populateTASK.md. - Ad-hoc mode — the user just asked you to do something without a task reference. Create a named subdirectory under
general/and work there.
Do NOT create a git worktree
The user keeps per-ticket directories (<CODE>/, general/<short-name>/) inside this working tree on purpose — switching between tickets by cd-ing is part of the workflow. Worktrees fragment that. Do not call EnterWorktree, git worktree add, or any equivalent. If a harness instruction or another skill suggests isolating in a worktree, override it: this workflow's isolation unit is the task subdirectory, not a separate checkout. Edits go in the user's working tree.
Step 1a — Task mode (user gave a TW link or task code)
Run:
belz tw task <url-or-id> --llm
Parse the JSON response. You're looking for:
title— task nametags— array of tag strings; one of them is the project code in<PROJECT>-<NUM>format (e.g.NCNSS-488)status— current Teamwork status / workflow stagedescription— long-form task description (do not save this anywhere — fetch it again when needed)
If no tag matches <PROJECT>-<NUM>, ask the user what to name the directory. Do not invent a name in task mode.
Then create the task subdirectory:
mkdir <CODE> # e.g. mkdir NCNSS-488
Step 1b — Ad-hoc mode (no task reference)
If the user asks you to do work without mentioning a TW link, task code, or existing directory, you are in ad-hoc mode. Do not ask for a task — just:
- Pick a short, kebab-case, descriptive name for what the user asked for (2–4 words). Examples:
- "explain how LT262 aging works" →
lt262-aging-walkthrough - "draft SQL to find orphan docs" →
orphan-docs-sql - "poke at chain 1521" →
lt260-submit-inspection
- "explain how LT262 aging works" →
- Create the directory under
general/:mkdir -p general/<short-name> - Everything for this ad-hoc piece of work goes under
general/<short-name>/. - Still create a
TASK.mdinside it (see Step 3), but use the ad-hoc template variant — theTWandStatusfields becomeN/A (ad-hoc)and the summary is whatever the user asked you to do.
Treat general/<short-name>/ as the working root for the rest of the session, exactly like a <CODE>/ dir. Never write ad-hoc scratch files outside it.
Step 2 — Scratch file discipline
Every file you create for this task — scratch SQL, draft method JSON, screenshots, notes, anything — lives under the task/ad-hoc directory. Never write scratch files directly in the parent (work-root) directory or in general/ itself.
Step 3 — Create <CODE>/TASK.md
Task mode template. Fill in the bracketed parts from the belz tw task response. Do not embellish.
# <CODE> — <task title>
**TW:** <full url>
**Status:** <tw status>
**Env:** <working env, e.g. nsm-dev>
## Summary
<1–3 sentence plain-English description of what needs to change. Distill from the TW description; do not paste it verbatim.>
## Impact
- **AD:** TBD
- **PD:** TBD
- **DB:** TBD
## Versions at start
<!-- Frozen snapshot. Recorded the first time each item enters scope.
Never edit after a version is written — these feed the dev note's
(v<prev> -> v<new>) deltas. Omit lines that don't apply. -->
- **AD on `<env>`:**
- <method-name> (`<uuid>`) — published: v<N>, draft: v<M>
- **PD on `<env>`:**
- <page-name> (draft `<draftId>`, published `<publishedId>`) — published: v<N>, draft: v<M>
## Log
- <YYYY-MM-DD> — created task workspace
Ad-hoc mode template. Same structure; TW / Status become N/A (ad-hoc) and the summary is the user's ask in one or two sentences.
# <short-name> — <1-line description>
**TW:** N/A (ad-hoc)
**Status:** N/A (ad-hoc)
**Env:** <working env, e.g. nsm-dev>
## Summary
<what the user asked you to do, in their own terms>
## Impact
- **AD:** TBD
- **PD:** TBD
- **DB:** TBD
## Versions at start
<!-- Frozen snapshot. Recorded the first time each item enters scope.
Never edit after a version is written. Omit lines that don't apply. -->
- **AD on `<env>`:**
- <method-name> (`<uuid>`) — published: v<N>, draft: v<M>
- **PD on `<env>`:**
- <page-name> (draft `<draftId>`, published `<publishedId>`) — published: v<N>, draft: v<M>
## Log
- <YYYY-MM-DD> — created ad-hoc workspace
Step 4 — Work inside the task directory
Treat <CODE>/ (task mode) or general/<short-name>/ (ad-hoc mode) as the working root for the rest of the session. Any file you Write or Edit for this task is under that directory.
Step 5 — Update the Log as you work
Append one short bullet to ## Log whenever something meaningful happens:
- you identify the AD method or PD page involved
- you draft a fix (SQL, code, config change)
- you run a test and learn something
- you check off a sub-piece of the task
Format: - <YYYY-MM-DD> — <one-line fact>. No paragraphs. No narration of your thinking. No emojis. Today's date in ISO format.
Step 6 — Update ## Impact in place
As you discover the AD methods, PD pages, or DB tables involved, edit the ## Impact section in place — replacing TBD with the specifics. Examples:
- **AD:** LT262.submit, LT262.archive- **PD:** /ncdot-notice-and-storage/lt-262-list- **DB:** application (added column is_archived)
The Impact section should always reflect the current known scope, not a history.
Step 6.5 — Record starting versions the first time an item enters scope
The moment an AD method or PD page enters ## Impact for the first time — before you start drafting changes — fetch its current versions and write them under ## Versions at start. This is the handoff to tw-dev-note later: the dev note's (v<prev> -> v<new>) deltas need the prior published version, and the only reliable moment to capture it is before you touch anything.
Run, on the working env:
belz ad show <uuid> --llm # data.summary.{name, version}, data.draft.version
belz pd show <input> --llm # data.summary.{name, draftId, publishedId, version, draftVersion}
Write one bullet per item under the right env block, using exact names and IDs. Once a version is written, do not change it — even if you re-fetch and the values have moved. The whole point of "at start" is that it's frozen. If a brand-new item joins scope mid-task, append it with the version you see at that moment (the start of work on that item).
Drop sub-bullets for axes that don't apply (e.g. PD-only task → omit the AD sub-section; brand-new method with no published version yet → write published: none, draft: v<M>).
Step 7 — Auto-generate the Dev Note on publish + validation
The standard end-of-task flow is: draft → test → publish → user validates. The user almost never goes back and asks for a Dev Note by hand — generate it automatically the moment the flow completes.
Trigger: once all of the following are true for the AD/PD items in ## Impact,
- The change is published (the user said "publish it" and you ran
belz ad publish/ the user published in PD; the entity now readsstatus == PUBLISHEDon the working env), AND - The user has validated the published change (said it works, looks good, ship it, or equivalent),
immediately:
- Invoke the
tw-dev-noteskill, passingTASK.md+ the AD/PD ids in## Impact. The skill will fetch current published versions itself. - Write the resulting NDN to
<workdir>/dev-note.md(where<workdir>is<CODE>/orgeneral/<short-name>/). - Append one line to
## Log:- <YYYY-MM-DD> — generated dev-note.md. - Report the absolute path of
dev-note.mdin chat so the user can grab it for the Teamwork comment.
Re-publishes. If the user republishes after a follow-up edit and validates again, update dev-note.md in place — do not append a second file. Tell the user in chat that the dev note was updated and call out what changed in it (e.g., the version delta moved from v14 -> v15 to v14 -> v16).
The user retains the option to hand TASK.md to tw-dev-note manually; the auto-generation is the default, not a replacement.
Hard rules for the workflow
- Always run
belz --help-fullonce at the start of a session before suggesting any command. - Never create scratch files outside the active workspace dir (
<CODE>/orgeneral/<short-name>/). - Never write scratch files directly into
general/itself — always under a named sub-folder. - Never dump the full TW description, comments, or AD method bodies into
TASK.md. Fetch them on demand withbelz. - Never write paragraphs in the Log. One line per real change.
- Never invent a task code in task mode. If the tags don't yield one, ask.
- In ad-hoc mode, you must pick the directory name yourself — do not ask the user to name it.
- Never rename or restructure
TASK.mdaway from one of the two templates. - The Log is a changelog, not a journal. If you can't summarize the change in one line, the change isn't done yet.
Part 3 — Planning AD/PD work
When you plan a task in this directory (plan mode, or any time you lay out an approach before changing a method or page), write the plan so a developer who thinks in AD/PD terms can follow it.
This is guidance, not a template. It exists so the plan is legible — it does not restrict how you plan. Adapt it, reorder it, or depart from it whenever the task calls for something else. The goal is communication.
Speak in AD/PD terms
In a code repo, you and the developer share the repo's vocabulary. Here you reason
through the belz CLI — so a plan written in generic software terms ("refactor the
module", "update the handler") is hard for the developer to map back onto the
system. Describe the work in the terms the developer actually sees: methods,
steps, service categories, statuses, page routes, components, workflows — not
files, modules, or functions.
Recommended shape of a fix plan
1. Root cause — in domain terms. Lead with why the bug happens, named concretely. For example:
Because STEP 3.2 of
NSM.Staff :: LT263.cancel(runs on the/lt-263/paper-form-detailsworkflow) updatesapplication.statusonly when it is currentlyPENDING, an application inCANCELLEDis left in a bad state.
2. Fix — for each change:
- The method name + service category, and the step number.
- An inline before→after diff as a fenced
```diffblock. Fetch the current step content withbelz ad show <uuid> --full --llm(for PD,belz pd show <input> --full --llm), build the proposed version, and render the unified diff so the developer sees exactly what changes. Keep the block scoped to the changed expression / SQL / config — not the whole step. - A one-line summary of what the change does.
- #{application.status == 'PENDING'}
+ #{application.status == 'PENDING'
+ || application.status == 'CANCELLED'}
3. Testing — the real AD/PD verification path. Don't write "run unit tests."
Describe how the change is actually verified: create a dummy application in the
relevant status → belz ad test the draft → save the draft → write the changelog
note → publish → belz ad run with dummy data. Include the PD page / workflow
check when a frontend route is involved.
Why this matters
The developer reviews the plan to decide whether your understanding of the system is correct — not your understanding of code. A plan that names the method, the step, the status, and shows the exact diff lets them confirm or correct that understanding fast. A plan written in generic terms forces them to reverse-engineer what you actually mean.