portal-block-pipeline — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited portal-block-pipeline (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Blocks are never created raw. A spec flows through gated specialist stages, each one an agent in .claude/agents/. This skill is the thin orchestration map; the how of block authoring lives in the global skills — load `zportal` (zPortal API + the two-field block structure), `currentblock` (currentBlock.queryResults data access), and `decompose-html-to-zportal-blocks` (splitting a monolith into blocks) — and the enforced rules in `assets/conventions.md` + house style in `assets/design.md`. Do not work from memory; read those.
spec → builder → stylist → responsive → debugger → adversary → advisor → ship
(build) (polish) (mobile) (fix bugs) (break it) (align)Run it via the `/portal-build` command (.claude/commands/portal-build.md) for one block, or the `.claude/workflows/portal-block-pipeline.js` workflow for a hands-off run that loops automatically. Drive each stage with the Task tool and pass the previous stage's output (the `block_id` + its notes) into the next — stages share state through that handoff, not through re-discovery.
| Stage | Agent | Does | Hands off |
|---|---|---|---|
| Build | portal-block-builder | discovers data, verifies real columns, authors the two fields, binds via ui_queries, validates, creates | block_id, bound query_id/datasource, exact column aliases, fallbacks/async paths, open questions |
| Style | portal-block-stylist | applies assets/design.md — hierarchy, color, type, spacing, elevation. CSS + structure only; never touches JS logic or the binding | restyled block_id, design decisions |
| Responsive | portal-responsive-specialist | breakpoints, fluid grids, ≥44px touch targets, no overflow (see the portal-responsive skill) | breakpoints handled, residual width risks |
| Debug | portal-block-debugger | fixes runtime footguns: the $ trap, AMD/window.define race, queryResults shape, dropped :root tokens, missing loaded-callback, re-render leaks | fixes applied, anything still suspect |
| Adversary | portal-block-adversary | read-only gate — red-teams for silent-data traps + edge cases, with evidence | findings list (severity + blocking) and a `ship` / `needs-fixes` verdict |
| Advisor | portal-block-advisor | read-only — does it serve the business question, the user, the data? | substance/UX recommendations |
Every stage grounds itself first in assets/conventions.md + assets/design.md and confirms the live portal version with check_connection (currently v1.19; data read synchronously from currentBlock.queryResults[n]).
validate_block gates each authoring stepAny stage that mutates the block (builder, stylist, responsive, debugger) must call `validate_block` on its json_data + css before create_block/update_block. Fix every error and structural warning; don't write until it's clean. validate_block is the enforced floor (it catches no_raw_dollar, unscoped CSS, section-separation, safety) — the adversary catches what it can't.
The cross-stage footgun: an update_block on an already-bound block MUST re-send the existing ui_queries, or the binding is wiped and the block goes blank. Stylist, responsive, and debugger all get_resource resource="block" first and re-send ui_queries verbatim.
The adversary is the decision point. If it returns any blocking:true finding, its verdict is needs-fixes → loop back to the debugger with those findings, then re-run the adversary. Cap at ~2 rounds; if still blocked, surface the remaining findings to the user rather than shipping. A clean adversary pass (ship) advances to the advisor, then ship.
portal-responsive skill).theme-factory / zuar-theme).Splitting a monolithic HTML dashboard into many blocks is a pre-pipeline step — use the global `decompose-html-to-zportal-blocks` skill, then run each resulting block through this pipeline.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.