☰
VSuite

Enterprise pack guide

This guide covers how an organisation creates, packages, verifies, distributes, deploys, and connects its own vsuite packs. It builds on three reference pages and does not repeat them:

The worked example here is the contoso pack in tests/fixtures/packs/contoso/. Its file listings below are checked against the fixture by tests/docs-snippets.test.ts, and the command output was captured from the built CLI (node packages/cli/dist/main.js) at vsuite 0.4.0.

1. Overview and concepts

A pack is a directory of Liquid templates plus a vsuite-pack.yaml manifest. A project lists packs in vsuite.json, picks which agents and skills come from them, and vsuite generate renders them for every configured target (OpenCode, Claude Code, GitHub Copilot) with the same engine as the built-in catalog.

A pack can A pack cannot
Add new agents (agents/<id>.md.liquid) and skills (skills/<id>/SKILL.md.liquid). Override individual built-in fragments; it replaces a whole agent or skill body.
Override a built-in agent or skill by using its id; omitted front matter is inherited. Run code: there are no hooks, scripts, or custom filters.
Share text through pack:<name> partials (partials/<name>.md.liquid). Include arbitrary files: include, layout, and block are disabled; render accepts only vsuite: and pack: names.
Place the built-in vsuite:* sections (skills, stack, metrics, memory, telemetry, roster, …) where it wants; required ones it skips are auto-appended. Produce non-deterministic output: the date filters and sample are disabled.
Read project data: stack, preferences, capabilities, roster, target. Read variables outside the context (TPL_UNKNOWN_VAR).

The built-in catalog is always available. A pack only affects entries a project explicitly points at it ("source": "pack:<name>"), plus new pack-only ids the project adds.

How a pack flows into generated files:

flowchart LR
  A[vsuite.json<br/>packs + sources] --> B[Resolve source<br/>path / npm / git]
  B --> C[Read and validate<br/>manifest, layout, front matter]
  C --> D{Integrity matches<br/>vsuite.lock.json?}
  D -- "no, npm/git" --> X[Stop: PACK_INTEGRITY]
  D -- "no, path" --> W[Warn and relock]
  D -- yes --> E[Merge with catalog<br/>by id]
  W --> E
  E --> F[Render Liquid<br/>per agent, skill, target]
  F --> G[Auto-append missing<br/>required sections]
  G --> H[Lint Markdown<br/>MD_LINT]
  H --> I[Write target files<br/>.opencode, .claude, .github]

2. Planning an enterprise pack

One organisation pack or several

Model When it fits Watch out for
One org pack (@contoso/vsuite-pack) Shared policy, one platform team owns agent definitions. Every team gets every change; release cadence is shared.
Org pack + team packs Teams add domain agents on top of org policy. Two packs defining the same id fail with PACK_CONFLICT; the project must choose one with source: "pack:<name>". Agree id prefixes per pack.
Repo-local pack (path:./.vsuite/packs/team) Experiments, single-repo agents. No version; changes relock silently with a warning.

Partials are private to their pack: pack:<name> resolves only inside the same pack, so a team pack cannot render the org pack’s partials. Shared wording must be copied or kept in one pack.

Naming and versioning

  • Pack id (id in the manifest): [a-z0-9-]+, for example contoso. Projects can rename it locally with pack add --name.
  • New ids: prefix agents and skills that are new to the catalog with the org name (contoso-secure-coding) so they never collide with future built-ins or other packs. Use a bare built-in id (code-reviewer) only when you intend to override it.
  • description (manifest): optional one-line summary of the pack, shown in the UI and sent to the AI assistant.
  • version: semver. Bump it on every release; major for removed or renamed ids or changed requiredSkills, minor for new ids, patch for wording.
  • contextVersion: 1 or 2 (current: 2) in this release. A breaking context change in vsuite gets a new version.
  • vsuite: the range of vsuite releases you test against, for example ">=0.4". A release outside the range fails with PACK_MANIFEST.

Override or new agent

flowchart TD
  S[Need different agent behaviour] --> Q1{Same job as a<br/>built-in agent?}
  Q1 -- no --> N[New agent with a prefixed id<br/>description required]
  Q1 -- yes --> Q2{Should every project using<br/>the pack get the change<br/>when it selects the pack?}
  Q2 -- yes --> O[Override the built-in id<br/>projects opt in per agent]
  Q2 -- "no, only extra rules" --> K[Keep the built-in agent and<br/>add a pack skill it can be given]

Overrides replace the whole body, so you own its upkeep when the built-in improves. Prefer a new skill when you only need to add rules.

3. Tutorial: the Contoso pack

The pack adds a compliance-reviewer agent and a contoso-secure-coding skill, overrides code-reviewer, and shares one contoso-policy partial.

contoso-pack/
├── vsuite-pack.yaml
├── agents/
│   ├── code-reviewer.md.liquid
│   └── compliance-reviewer.md.liquid
├── partials/
│   └── contoso-policy.md.liquid
└── skills/
    └── contoso-secure-coding/
        └── SKILL.md.liquid

Other files (README, package.json, CI config) are ignored by vsuite and are not part of the integrity hash.

Manifest

id: contoso
name: Contoso Engineering Pack
version: 1.0.0
contextVersion: 2
vsuite: ">=0.4"

Shared partial

Uses pack.id, pack.version, and capabilities.agentMetrics. The {%- trims keep the output free of blank lines when the condition is false.

## Contoso Engineering Policy
 
- Policy source: {{ pack.id }} pack {{ pack.version }}.
- Every change references a work item in the commit body (`Work-Item: CTS-1234`).
- Secrets come from the Contoso key vault; never commit credentials, tokens, or `.env` files.
- Personal data follows the Contoso data classification: `public`, `internal`, `confidential`, `restricted`.
- Findings use the Contoso severity scale: `SEV1` blocks release, `SEV2` blocks merge, `SEV3` is tracked.
{%- if capabilities.agentMetrics %}
- Record compliance findings in the job-metrics log so audits can trace them.
{%- endif %}

New agent: compliance-reviewer

New id, so description is required. It requires the pack skill, loops over project.stack, renders the pack partial, and places vsuite:skills; telemetry, stack, metrics, and memory are auto-appended (each renders nothing when its condition is off). Agent and skill front matter may also set whenToUse, decision-oriented prose for the AI assistant that falls back to description when omitted.

---
description: Reviews diffs for Contoso compliance, data-handling, and secure-coding policy violations.
tools: [read, search, todo]
requiredSkills: [contoso-secure-coding]
role: specialist
---
## Identity
 
- Role: Compliance reviewer for Contoso services.
- Personality: Methodical, policy-literate, evidence-driven.
- Experience: Knows that audit findings start as small, unreviewed shortcuts.
 
## Core Mission
 
Find compliance and data-handling violations in a supplied diff before it merges.
 
1. Classify every data field the change touches.
2. Check the change against the Contoso policy and the secure-coding skill.
3. Report each finding with file, line, Contoso severity, and the policy clause.
{%- if project.stack.size > 0 %}
 
## Stack Focus
{% for entry in project.stack %}
- `{{ entry.category }}`: check {{ entry.labels | join_human }} against the secure-coding rules for that technology.
{%- endfor %}
{%- endif %}
 
{% render "pack:contoso-policy" %}
 
{% render "vsuite:skills" %}
 
## Review Contract
 
- Reply `APPROVE`, `CHANGE: <finding>`, or `BLOCK: <SEV1 finding>`.
- Review read-only; do not edit files.

project.stack holds only the stack categories the agent is configured for (the stack array on the agent entry in vsuite.json). With "stack": ["backend", "orm", "database"] on a NestJS + Prisma + PostgreSQL project, the generated section is:

## Stack Focus
 
- `backend`: check NestJS against the secure-coding rules for that technology.
- `orm`: check Prisma against the secure-coding rules for that technology.
- `database`: check PostgreSQL against the secure-coding rules for that technology.

Override: code-reviewer

code-reviewer exists in the catalog, so the template inherits description, tools, and the rest. requiredSkills adds the Contoso skill to the skills the project configures (the generated agent lists both review-priority-tiers and contoso-secure-coding).

---
requiredSkills: [contoso-secure-coding]
---
## Identity
 
- Role: Code reviewer for Contoso repositories.
- Personality: Constructive, specific, evidence-driven.
- Experience: Knows that the best reviews teach, not just criticize.
 
## Core Mission
 
Review verified diffs against Contoso standards in one pass.
 
1. Classify every finding as `BLOCK`, `CHANGE`, or `NOTE`.
2. Name the file, line, and correction for each finding.
3. Explain why each finding matters.
 
{% render "vsuite:efficiency" %}
 
{% render "vsuite:evidence" %}
 
{% render "vsuite:review-contract" %}
 
{% render "pack:contoso-policy" %}

Skill: contoso-secure-coding

Skills have no required sections. roster.specialists is guarded so the line appears only when there are specialists to name.

---
description: Applies the Contoso secure-coding checklist to a change. Use when code handles input, secrets, authentication, or personal data.
---
# Contoso Secure Coding
 
Checklist from the {{ pack.id }} pack, version {{ pack.version }}.
 
1. Validate every external input at the trust boundary; reject, do not sanitize silently.
2. Load secrets from the Contoso key vault at runtime; never log them.
3. Require authentication and authorization on every non-public endpoint.
4. Mask `confidential` and `restricted` fields in logs, errors, and analytics.
5. Pin dependencies and keep the lockfile in the same change as the manifest.
{%- if roster.specialists.size > 0 %}
 
Escalate to a specialist when a finding is outside your role: {{ roster.specialists | map: "id" | join_human }}.
{%- endif %}

Validate and generate

$ vsuite pack validate ../contoso-pack --strict
Pack ../contoso-pack is valid
[exit 0]

Connecting it to a project (pack served from a git mirror; <tmp> stands for the local directory):

$ vsuite pack add git:file://<tmp>/contoso-pack#v1.0.0 --name contoso
Added pack contoso: Contoso Engineering Pack 1.0.0
  agents added: compliance-reviewer
  agents overriding the catalog: code-reviewer
  skills added: contoso-secure-coding
  skills overriding the catalog: -
  instructions added: -
Select entries with `vsuite agent use <id> --from contoso`, then run `vsuite generate`.
[exit 0]
 
$ vsuite agent use code-reviewer --from contoso
agent code-reviewer now uses pack:contoso
Run `vsuite generate` to update generated files.
[exit 0]
 
$ vsuite agent use compliance-reviewer --from contoso
agent compliance-reviewer now uses pack:contoso
  added agent compliance-reviewer as a specialist
Run `vsuite generate` to update generated files.
[exit 0]
 
$ vsuite generate --strict
warning [claude-code] skills-not-enforced: code-reviewer: claude-code preloads the listed skills but cannot deny unlisted ones
warning [claude-code] skills-not-enforced: compliance-reviewer: claude-code preloads the listed skills but cannot deny unlisted ones
warning [claude-code] coordinator-main-thread: orchestrator: Claude Code enforces canCall only when the coordinator runs as the main thread; start it with "claude --agent orchestrator"
.opencode/agents/code-reviewer.md
.claude/agents/code-reviewer.md
.opencode/agents/compliance-reviewer.md
.claude/agents/compliance-reviewer.md
.opencode/agents/orchestrator.md
.claude/agents/orchestrator.md
.opencode/skills/agent-efficiency-protocol/SKILL.md
.claude/skills/agent-efficiency-protocol/SKILL.md
.opencode/skills/contoso-secure-coding/SKILL.md
.claude/skills/contoso-secure-coding/SKILL.md
.opencode/skills/review-priority-tiers/SKILL.md
.claude/skills/review-priority-tiers/SKILL.md
.opencode/opencode.json
[exit 0]
 
$ vsuite pack list
contoso  git:file://<tmp>/contoso-pack#v1.0.0  1.0.0  locked: a3c0479526230b7337761631e7c8bc49aab0f474 sha256-1Dv4A/5XhtDH  integrity: ok
  agents added: compliance-reviewer
  agents overriding the catalog: code-reviewer
  skills added: contoso-secure-coding
  skills overriding the catalog: -
  instructions added: -
[exit 0]

The [claude-code] warnings are target capability notes, not pack problems; --strict fails only on MD_LINT. agent use … --from contoso on a new id adds the agent as a specialist and to the coordinator’s canCall. The pack skill is generated because an agent requires it; use vsuite skill use <id> --from contoso when the pack overrides a catalog skill.

4. Local development loop

  1. Keep the pack in its own repository (or a folder of a monorepo) and point a test project at it with path::

    vsuite pack add path:../contoso-pack --name contoso
  2. Edit templates, then run vsuite pack validate ../contoso-pack --strict. It needs no project and test-renders every template against built-in fixture contexts (empty and full stack, each target, metrics and memory on and off), so it catches if branches your test project never hits.

  3. Run vsuite generate in the test project. A changed path: pack is relocked with a warning:

    warning [pack:contoso] vsuite.lock.json PACK_INTEGRITY: [contoso] local pack changed since vsuite.lock.json was written (sha256-7TCm1ruHLs/rbIMndiao/lTwkVY9iUoH9gkqu5orYgI= → sha256-IBQUUtPF+iCe23C1icWn7QA0AY09gT7T9bqLx+SIuz4=); lock entry rewritten
  4. Or use the desktop app’s Preview tab: it shows the exact generated Markdown for the selected agent or skill and target, marks auto-appended required sections, and lists diagnostics with file and line. It refreshes when files change under a path: pack folder (folders outside the project must have been chosen with the Packs tab folder picker to be watched).

Use --json in scripts; each entry has code, pack, file, line, column, hint, and issues.

Reading errors

A pack with a typo in skill front matter and an unknown variable in a new agent:

$ vsuite pack validate broken
skills/contoso-secure-coding/SKILL.md.liquid:2:13 PACK_FRONTMATTER [contoso] 2 issue(s)
  skills/contoso-secure-coding/SKILL.md.liquid:2:13: descriptio: unknown key
  skills/contoso-secure-coding/SKILL.md.liquid:2:1: description: required for ids that do not override a built-in (Fix the template front matter; every issue is listed.)
  skills/contoso-secure-coding/SKILL.md.liquid:2:13 descriptio: unknown key
  skills/contoso-secure-coding/SKILL.md.liquid:2:1 description: required for ids that do not override a built-in
agents/release-notes.md.liquid:6:11 TPL_UNKNOWN_VAR [contoso] undefined variable: project.stacks (Use only variables defined by the TemplateContext schema.)
Pack broken has 2 error(s)
[exit 1]

Format: file:line:column CODE [pack] message (hint), then one line per issue.

Code Typical cause in an org pack Fix
PACK_FETCH Wrong path, registry auth, unreachable git host, tag not found. Check the source string and credentials; run the npm/git command by hand.
PACK_INTEGRITY npm/git content changed under the same source (republished tag, new version in range). Review the change, then vsuite pack update <name> or generate --update-packs.
PACK_MANIFEST Bad manifest field, or the running vsuite is outside the vsuite range. Fix the manifest or upgrade vsuite.
PACK_FRONTMATTER Typo in a key, missing description on a new id. Fix front matter; every issue is listed.
PACK_LAYOUT Unexpected file name, id with capitals or _, file over 256 KB, symlink leaving the pack. Rename or move the file.
PACK_CONTEXT_VERSION contextVersion not supported by this vsuite. Set contextVersion: 1 or 2, or release a pack for the newer context.
PACK_CONFLICT Org and team pack define the same id. Set source: "pack:<name>" for that entry, or rename one id.
PACK_MISSING_ENTRY The project selects an id the pack no longer ships. Restore the id or move the project to --from catalog.
TPL_UNKNOWN_VAR Misspelt variable, or one not in the context. Check the context reference.
TPL_UNKNOWN_FILTER A filter from another Liquid flavour. Use Liquid built-ins or md_escape, code, join_human.
TPL_UNKNOWN_TAG include, layout, block. Use {% render "pack:<name>" %}.
TPL_BAD_PARTIAL render of a missing partial or a path. Add partials/<name>.md.liquid or fix the name.
TPL_LIMIT Runaway loop, huge output, NUL character. Simplify the template.
MD_LINT Rendered Markdown issue (often blank-line handling around if). Use {%-/-%} trims; the report gives outputLine and templateLine.

5. Packaging and distribution

The pack root (the directory with vsuite-pack.yaml) must be the package root for npm and the repository root for git. There is no subdirectory option for npm: or git: sources.

Channel Source string Lock resolved Best for Notes
npm (private registry) npm:@contoso/vsuite-pack@1.0.0 exact version Org-wide releases, existing npm tooling. Range specs (@^1.0.0) resolve to the newest matching version on every fetch; see Verification.
git git:https://git.contoso.com/platform/vsuite-pack.git#v1.0.0 or #<commit sha> 40-hex commit SHA Teams without a registry, signed tags. URLs must be https://, ssh://, git@host:path, or file://; transport helpers (ext::) are rejected. Refs are tags, branches, or 7–40 hex SHAs.
path path:./.vsuite/packs/team or path:../contoso-pack project-relative path Monorepos, local development. Content changes relock with a warning; no version pinning.

Fetched npm and git packs are cached under node_modules/.cache/vsuite/packs in the consuming project.

npm

package.json in the pack repository:

{
  "name": "@contoso/vsuite-pack",
  "version": "1.0.0",
  "description": "Contoso agents and skills for vsuite",
  "files": ["vsuite-pack.yaml", "agents", "skills", "partials"],
  "publishConfig": { "registry": "https://npm.contoso.com/" }
}

Keep version equal to the manifest version. Publish with npm publish.

vsuite runs npm view <spec> version in the project directory and npm pack <name>@<version> in a temporary directory. Configure the scope registry and token where both see it: user ~/.npmrc or NPM_CONFIG_* environment variables in CI. A project-level .npmrc applies only to npm view.

@contoso:registry=https://npm.contoso.com/
//npm.contoso.com/:_authToken=${NPM_TOKEN}

git

Tag each release with the manifest version and reference the tag or the commit:

git tag -s v1.0.0 -m "contoso pack 1.0.0"
git push origin v1.0.0

vsuite resolves tags and branches with git ls-remote, fetches a shallow clone, and locks the commit SHA. Authentication is whatever your git uses (SSH agent, credential helper).

Release sequence

sequenceDiagram
  participant A as Pack author
  participant R as Pack repo CI
  participant G as Registry / git host
  participant P as Consumer repo
  participant C as Consumer CI
  A->>R: PR with template changes
  R->>R: vsuite pack validate . --strict
  R->>R: generate --strict in a sample project
  A->>G: npm publish or signed tag v1.1.0
  P->>P: change source to 1.1.0, vsuite pack update
  P->>P: vsuite generate, commit vsuite.json, vsuite.lock.json, outputs
  P->>C: PR
  C->>C: verify tag or npm signatures (external)
  C->>C: vsuite generate --strict, git diff --exit-code

6. Verification and supply-chain integrity

What vsuite verifies

vsuite does not implement pack signatures or signature verification. It pins packs:

  • vsuite.lock.json records each pack’s source, resolved (exact npm version, git commit SHA, or project-relative path), and integrity: sha256- plus base64 of a SHA-256 over the sorted list of pack files with their per-file SHA-256 (CRLF normalised to LF). Only the files vsuite reads count: the manifest, agents, skills, and partials.
  • npm: and git:: if fetched content does not match the locked integrity, generate and the UI preview stop with PACK_INTEGRITY. Nothing is written until you accept the change with vsuite pack update [name] or vsuite generate --update-packs.
  • path:: a mismatch warns and relocks.

Lockfile after the tutorial:

{
  "lockfileVersion": 2,
  "packs": {
    "contoso": {
      "source": "git:file://<tmp>/contoso-pack#v1.0.0",
      "resolved": "a3c0479526230b7337761631e7c8bc49aab0f474",
      "integrity": "sha256-1Dv4A/5XhtDHi7nu2u0zbs/jYHzNx6XSrQ3Cs3V0Izc=",
      "contextVersion": 2,
      "generatedSkills": [
        "contoso-secure-coding"
      ],
      "generatedAgents": [
        "code-reviewer",
        "compliance-reviewer"
      ]
    }
  }
}

What triggers PACK_INTEGRITY

Any change in the fetched files under the same source: a moved git tag or branch, a new npm version matching a range, or a republished package. Here the v1.0.0 tag was moved to a new commit:

$ vsuite generate
vsuite.lock.json:0:0 PACK_INTEGRITY [contoso] integrity mismatch: locked sha256-1Dv4A/5XhtDHi7nu2u0zbs/jYHzNx6XSrQ3Cs3V0Izc=, fetched sha256-kHIt52Gx+C/GGu4CcBFGVBrqK/o9DTnWvJAm2QmWkEE= (The pack changed since vsuite.lock.json was written; review it, then re-run with updatePacks.)
[exit 1]
 
$ vsuite pack update contoso
contoso: updated 1.0.0 (sha256-1Dv4A/5XhtDH -> sha256-kHIt52Gx+C/G)
[exit 0]
-      "resolved": "a3c0479526230b7337761631e7c8bc49aab0f474",
-      "integrity": "sha256-1Dv4A/5XhtDHi7nu2u0zbs/jYHzNx6XSrQ3Cs3V0Izc=",
+      "resolved": "f27401d6287d2e26d4c39af2fdd6529dd7ca7aaf",
+      "integrity": "sha256-kHIt52Gx+C/GGu4CcBFGVBrqK/o9DTnWvJAm2QmWkEE=",

pack update only relocks; run vsuite generate afterwards to regenerate files. A lock diff where resolved changes while the version in source does not is a red flag: review what changed before accepting it.

For reproducible builds, use exact npm versions (@1.0.0) or commit SHAs rather than ranges or moving branches.

Organisational practices outside vsuite

These are external practices that compose with lockfile pinning. vsuite does not perform or check any of them; signature verification inside vsuite is future work (the lockfile format leaves room for signature fields).

Practice Where What it adds
Signed release tags; CI runs git verify-tag v1.1.0 (or git verify-commit <sha>) on a clone of the pack repo before anyone runs vsuite pack update Pack repo, consumer CI Proves who released the content vsuite will lock.
npm provenance on publish (npm publish --provenance from CI) and npm audit signatures in consumer CI, where your private registry supports them Registry, consumer CI Registry signatures and build provenance for the package.
CODEOWNERS on vsuite.json and vsuite.lock.json (and generated agent folders) Consumer repos Pack source and lock changes need platform-team approval.
CI runs vsuite pack validate . --strict on every pack PR Pack repo No broken template reaches the registry.
CI runs vsuite generate --strict and fails on a diff Consumer repos Committed outputs always match the locked pack.
Protected tags and immutable registry versions Git host, registry Prevents silent republish; vsuite would catch it as PACK_INTEGRITY, this prevents it.
flowchart LR
  subgraph External["Organisation controls (outside vsuite)"]
    S1[Signed tag / npm provenance]
    S2[CI: git verify-tag,<br/>npm audit signatures]
    S3[CODEOWNERS review of<br/>vsuite.json + lock]
  end
  subgraph Vsuite["vsuite"]
    V1[Fetch by version / SHA]
    V2[sha256 integrity<br/>vs vsuite.lock.json]
    V3[Validate, render, lint]
  end
  S1 --> S2 --> V1 --> V2 --> V3
  S3 --> V2
  V3 --> O[Committed agent files]

7. Deployment and rollout

Connecting a project

CLI:

vsuite pack add npm:@contoso/vsuite-pack@1.0.0 --name contoso
vsuite agent use code-reviewer --from contoso
vsuite agent use compliance-reviewer --from contoso
vsuite skill use <skill-id> --from contoso   # only for skills the pack overrides or the project selects
vsuite generate --strict
git add vsuite.json vsuite.lock.json .opencode .claude

Desktop app: Packs tab → add (folder picker, npm, or git); then in the agents or skills view pick the pack in the Definition select for overridden built-ins, or add pack-only entries from the From packs group; check the Preview tab; save and generate. Pack add, remove, and update are disabled while the config draft has unsaved changes.

Commit vsuite.json, vsuite.lock.json, and the generated target folders together.

CI

Availability: pack support requires vsuite 0.4.0 or later, which is not yet published to npm (the latest published version is 0.3.1). Until it is, the npx @krizic/vsuite@0.4.0 steps below will fail; run vsuite from a repository build instead (pnpm build, then node packages/cli/dist/main.js) or install a private build from your internal registry.

Pack repository (GitHub Actions; Gitea Actions accepts the same syntax):

name: pack
on: [pull_request, push]
jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
      - run: npx @krizic/vsuite@0.4.0 pack validate . --strict

Consumer repository:

name: agents
on: [pull_request]
jobs:
  generate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          registry-url: https://npm.contoso.com/
          scope: "@contoso"
      - run: npx @krizic/vsuite@0.4.0 generate --strict
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
      - run: git diff --exit-code

generate fails on PACK_INTEGRITY, so CI never accepts unreviewed pack content; never pass --update-packs in CI. Pin the vsuite version you run in CI to one inside the pack’s vsuite range. Insert your external verification step (for example git verify-tag against a clone of the pack repo) before generate.

Upgrading

  1. Change the source to the new version (npm:@contoso/vsuite-pack@1.1.0 or #v1.1.0) in vsuite.json.
  2. vsuite pack update contoso, then vsuite generate --strict.
  3. Open a PR with the vsuite.json, lock, and generated-file diffs; reviewers read the generated Markdown diff, not just the version bump.

Rollback

Goal Action
Previous pack release Revert the PR, or set the previous version or SHA as the source, then vsuite pack update contoso and vsuite generate.
One agent back to built-in vsuite agent use code-reviewer --from catalog, then vsuite generate.
Drop the pack vsuite pack remove contoso --reset-to-catalog, then vsuite generate.

Removal and cleanup

vsuite pack remove <name> fails with PACK_REFERENCED while entries still use the pack and lists them. --reset-to-catalog resets overrides to the catalog and removes pack-only agents and skills from vsuite.json. Their generated ids move to pendingRemovalAgents / pendingRemovalSkills in the lock, and the next vsuite generate deletes those files. Commit after that generate so the deletions land with the config change.

8. Governance and security

Trust model

Packs are trusted, code-adjacent content: they become instructions your agents follow and set agent tools. vsuite pins and hashes them and limits what templates can do, but there is no sandbox and no signature check. Treat a pack release like a dependency release. See Trust model.

Limits

Limit Value Error
Files per pack 500 PACK_LAYOUT
File size 256 KB PACK_LAYOUT
Ids [a-z0-9-]+ PACK_LAYOUT
Symlinks must resolve inside the pack PACK_LAYOUT
File content regular, UTF-8, no NUL PACK_LAYOUT
Template parse 1 Mi characters TPL_LIMIT
Render time 2000 ms TPL_LIMIT
Render memory 16 Mi units TPL_LIMIT

Pack PR review checklist

  • vsuite pack validate . --strict passes in CI.
  • version bumped (semver) and matches package.json / the tag.
  • vsuite range still covers the vsuite versions consumers run.
  • New ids are org-prefixed; overrides of built-in ids are intentional and noted in the changelog.
  • tools in front matter grant no more than the agent needs (for example, reviewers without edit or execute).
  • requiredSkills changes are listed in the changelog (consumers get them automatically).
  • No secrets, internal hostnames, or personal data in templates; everything in a pack ends up in every consumer repo.
  • Instructions do not tell agents to fetch and run remote content or bypass review.
  • Rendered output reviewed in a sample project (Preview tab or generate).

Ownership

Asset Owner
Pack repository and releases Platform or developer-experience team.
Signing keys, registry tokens Same team, managed by your secrets process.
vsuite.json, vsuite.lock.json in consumers Consumer team, with platform team as CODEOWNER.
Team packs The team, under the same checklist.

9. Troubleshooting

generate stops with PACK_INTEGRITY in CI but works locally. Someone ran pack update locally without committing the lock, or the source is a range or branch that moved. Commit the lock; pin exact versions or SHAs.

PACK_FETCH for an npm pack in CI. The registry or token is not visible to npm pack, which runs in a temporary directory. Configure it in user ~/.npmrc or environment variables, not only the project .npmrc.

PACK_FETCH: unsupported git url. Use https://, ssh://, git@host:path, or file://.

PACK_MANIFEST after upgrading vsuite. The new release is outside the pack’s vsuite range. Release a pack with a wider range after testing.

PACK_CONFLICT after adding a team pack. Both packs define an id. Set that entry’s source to the pack you want.

My override lost a built-in section. Required sections are auto-appended, but optional ones (vsuite:efficiency, vsuite:evidence, vsuite:review-contract, …) appear only where you render them.

Extra blank lines in output, or MD_LINT with --strict. Trim around tags: {%- if … %} / {%- endif %}. The report gives templateLine.

A pack-only agent’s files remain after removal. Run vsuite generate after pack remove; deletions are applied from the lock’s pending removals.

Is the pack signed? No; see Organisational practices outside vsuite.

References