npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@shardworks/cartograph-apparatus

v0.1.293

Published

The Cartograph — vision/charge/piece decomposition-ladder apparatus

Readme

@shardworks/cartograph-apparatus

The Cartograph stands up the decomposition-ladder substrate: a typed data layer for tracking long-lived patron intent across four levels — vision (top, patron-owned, long-lived) → charge (first decomposition, the unit of patron walkthrough) → piece (recursive, internal organization, self-nesting) → mandate (the existing leaf where rigs attach).

This commission lands the data-and-typed-API substrate plus a patron-facing CLI. There is no agent runtime and no downstream consumer in this package — those land in follow-on commissions. What ships here:

  • Three new writ types contributed to the Clerk: vision, charge, piece. Each uses a six-state mandate-clone lifecycle (no childrenBehavior cascade — patron-walkthrough semantics will be coordinated by the typed API and downstream consumers, not by registry-side cascade rules).
  • A typed ext['cartograph'] sub-slot stamped on each cartograph-typed writ, carrying the per-type lifecycle stage. Written exclusively through clerk.setWritExt so sibling sub-slots (e.g. ext['surveyor']) are preserved under concurrent writers. The cartograph contributes no companion books — writ.codex, writ.createdAt, and writ.updatedAt are the canonical sources for those fields, and ext['cartograph'].stage is the only field the cartograph carries beyond what Clerk already records.
  • A CartographApi exposed via provides that is the only layer enforcing the ladder's parent invariants:
    • vision has no parent;
    • charge.parentId must be a vision;
    • piece.parentId must be a charge or piece. Raw clerk.post({ type: 'vision' }) continues to succeed without parent-type checks — the typed API is the validator. The mandate-side rules (mandate may attach under any non-terminal node) stay where they are.
  • A patron-facing CLI surface contributed via supportKit.tools — three subcommand groups (nsg vision, nsg charge, nsg piece), each with five operations (create, show, list, patch, transition) plus the on-disk authoring tool nsg vision apply. The framework nsg auto-builder discovers the tools at startup and groups them by hyphen prefix; no edits to the framework CLI package are required. Every tool routes through the typed API above, so the parent invariants and lifecycle coupling hold for CLI-driven authoring.

The Cartograph requires stacks and clerk and recommends oculus. The Oculus writs page automatically renders the new types via the type-vocabulary helper; without oculus the data is invisible to the dashboard.


Installation

{
  "dependencies": {
    "@shardworks/cartograph-apparatus": "workspace:*"
  }
}

API

The Cartograph exposes a CartographApi via provides, accessible at runtime via guild().apparatus<CartographApi>('cartograph').

import type { CartographApi } from '@shardworks/cartograph-apparatus';

const cartograph = guild().apparatus<CartographApi>('cartograph');

// Create a vision (no parent permitted)
const vision = await cartograph.createVision({
  title: 'Land the agentic decomposition ladder',
  body: 'Long-form patron intent ...',
  codex: 'main',
});

// Create a charge under that vision
const charge = await cartograph.createCharge({
  parentId: vision.id,
  title: 'Stand up the data substrate',
  body: 'First decomposition ...',
});

// Create a piece under the charge
const piece = await cartograph.createPiece({
  parentId: charge.id,
  title: 'Pick an ext-slot shape',
  body: 'Internal organization ...',
});

// Pieces can self-nest
const subPiece = await cartograph.createPiece({
  parentId: piece.id,
  title: 'Decide how createX writes both rows atomically',
  body: 'Internal sub-piece ...',
});

Each createX opens a single stacks.transaction(...), replicates Clerk's post() validation byte-for-byte (parent existence, parent-not-terminal, codex inheritance, id generation), writes the writ row, and stamps ext['cartograph'] via clerk.setWritExt. The setWritExt's inner tx flattens via Stacks' nested-tx semantics, so both writes commit atomically and CDC sees one coalesced create event on the writs book. Each transitionX wraps clerk.transition

  • clerk.setWritExt('cartograph', ...) in one outer transaction — both inner txs flatten and CDC sees one coalesced update event.

CartographApi

interface CartographApi {
  // Vision
  createVision(req: CreateVisionRequest): Promise<VisionDoc>;
  showVision(id: string): Promise<VisionDoc>;
  listVisions(filters?: VisionFilters): Promise<VisionDoc[]>;
  patchVision(id: string, fields: Partial<Omit<VisionDoc, 'id'>>): Promise<VisionDoc>;
  transitionVision(id: string, to: { phase: WritPhase; stage: VisionStage; resolution?: string }): Promise<VisionDoc>;

  // Charge
  createCharge(req: CreateChargeRequest): Promise<ChargeDoc>;
  showCharge(id: string): Promise<ChargeDoc>;
  listCharges(filters?: ChargeFilters): Promise<ChargeDoc[]>;
  patchCharge(id: string, fields: Partial<Omit<ChargeDoc, 'id'>>): Promise<ChargeDoc>;
  transitionCharge(id: string, to: { phase: WritPhase; stage: ChargeStage; resolution?: string }): Promise<ChargeDoc>;

  // Piece
  createPiece(req: CreatePieceRequest): Promise<PieceDoc>;
  showPiece(id: string): Promise<PieceDoc>;
  listPieces(filters?: PieceFilters): Promise<PieceDoc[]>;
  patchPiece(id: string, fields: Partial<Omit<PieceDoc, 'id'>>): Promise<PieceDoc>;
  transitionPiece(id: string, to: { phase: WritPhase; stage: PieceStage; resolution?: string }): Promise<PieceDoc>;
}

The lifecycle-coupled transitionX methods update both writ.phase and writ.ext['cartograph'].stage atomically, inside a single Stacks transaction. The caller specifies both the target phase and the target stage explicitly because a single phase may map to multiple stages depending on context (e.g. a charge moving to failed could mean stage dropped or stage validated depending on outcome).

Projections

interface VisionDoc { id: string; stage: VisionStage; codex?: string; createdAt: string; updatedAt: string; }
interface ChargeDoc { id: string; stage: ChargeStage; codex?: string; createdAt: string; updatedAt: string; }
interface PieceDoc  { id: string; stage: PieceStage;  codex?: string; createdAt: string; updatedAt: string; }

type VisionStage = 'draft' | 'active' | 'sunset' | 'cancelled';
type ChargeStage = 'draft' | 'active' | 'validated' | 'dropped';
type PieceStage  = 'draft' | 'active' | 'done' | 'dropped';

// Shape stored at writ.ext['cartograph'] (exported as CartographExt).
interface CartographExt { stage: VisionStage | ChargeStage | PieceStage; }

The minimal field set is deliberate — id, codex, createdAt, and updatedAt come straight from the writ row; stage comes from writ.ext['cartograph']. The [key: string]: unknown index signature on the projection types lets consumers grow the field set non-breakingly later. Vision text lives on writ.body and is not part of the projection.

Filters

VisionFilters, ChargeFilters, and PieceFilters mirror the PlanFilters shape from astrolabe — { stage?, codex?, limit?, offset? }. Lists are ordered by createdAt desc (newest first).

Support Kit

Books

The cartograph contributes no books — the per-writ stage lives in the Clerk-owned writ.ext['cartograph'] sub-slot, written through clerk.setWritExt. See ClerkApi.setWritExt's JSDoc for the canonical description of the plugin-keyed metadata slot. List queries filter by the dot-notation field ext.cartograph.stage; row counts are small in practice so the unindexed json_extract scan is acceptable.

Retro-cleanup of retired companion books

An earlier commission contributed three companion books (cartograph/visions, cartograph/charges, cartograph/pieces) that have since been retired in favour of the writ.ext['cartograph'] slot. Because Stacks' startup-time schema reconciliation is additive only, the underlying SQLite tables would otherwise persist on every existing on-disk database as dead-but-not-dropped storage. The cartograph's start() therefore issues three sequential stacks.dropBook calls — one each for visions, charges, and pieces — before any clerk.registerWritType calls. The drops are idempotent (silent no-op when the storage is already gone), so subsequent boots are no-ops. Historical row data is not migrated: the originating brief tolerates loss; this hook only retires the storage.

Writ Types (contributed to Clerk)

| Name | Description | |---|---| | vision | Top-level patron intent. No parent. Long-lived. | | charge | First decomposition under a vision; the unit of patron walkthrough. Parent must be a vision. | | piece | Recursive internal organization. Self-nests. Parent must be a charge or piece. |

Each writ type uses a six-state mandate-clone lifecycle: new (initial) → open (active) → stuck/completed/failed/cancelled; no childrenBehavior cascade.

CLI

Cartograph contributes three subcommand groups to nsg — one per writ type — with the same five operations under each:

| Command | Description | |---|---| | nsg vision create --title <t> --body <b> [--codex <c>] | Create a top-level vision (writ at phase: new, doc at stage: draft). | | nsg charge create --parent-id <vision> --title <t> --body <b> [--codex <c>] | Create a charge under a vision. | | nsg piece create --parent-id <charge\|piece> --title <t> --body <b> [--codex <c>] | Create a piece under a charge or piece (self-nests). | | nsg <type> show <id> [--format text\|json] | Show the cartograph projection joined with the writ row. Text mode mirrors nsg writ show's lifecycle-aware block; JSON returns { ...doc, writ: { ... } }. | | nsg <type> list [--stage <s>] [--codex <c>] [--limit <n>] [--offset <n>] [--format text\|json] | Tabular list (STAGE | ID | CODEX | TITLE | CREATED) ordered by createdAt desc. | | nsg <type> patch <id> --codex <c> | Patch the writ's codex (routed through clerk.edit so the writ row stays the single source of truth). Title and body live on the writ row — edit them via nsg writ edit. | | nsg <type> transition <id> --phase <writ-phase> --stage <doc-stage> [--resolution <r>] | Atomically advance both writ.phase and writ.ext['cartograph'].stage inside one Stacks transaction. Both --phase and --stage are required because a single phase may map to multiple stages depending on context. | | nsg vision apply <slug> [--severity <s>] [--deadline <d>] [--decay <d>] | Snapshot the on-disk vision at <GUILD>/vision/<slug>/ into a vision writ stamped with ext['cartograph']. Idempotent: first apply creates and binds; later applies sync the file's contents into the bound writ. CLI flags override sidecar values for the surveyor priority-hint payload. |

The CLI tools are read or write according to operation: show/list declare permission: 'read'; create/patch/transition/apply declare permission: 'write'. Every tool declares callableBy: ['patron'] — they are not exposed to anima or library callers in this commission. Only show and list accept the --format text|json flag; write tools return their result directly and the framework auto-stringifies.

Short-prefix id resolution (via clerk.resolveId) works on every id-bearing flag: nsg vision show w-mo123 and nsg charge create --parent-id w-mo123 both succeed when the prefix matches a single writ.

On-disk vision authoring

Visions are prose-heavy and long-lived; the patron-facing path is to author them in a normal editor on disk and snapshot the directory into the cartograph with nsg vision apply <slug>. The same code path handles first-time creation and Nth re-import — the binding is durable across applies, so the file tree is the source of truth for vision content while the cartograph remains the source of truth for lifecycle state and ext metadata.

File layout

<GUILD>/
└── vision/
    └── <slug>/
        ├── vision.md              # long-form vision text → writ.body
        └── vision-metadata.yml    # required sidecar

The slug must be a single directory name (lowercase letters, digits, hyphens, or underscores; no path separators, no leading dots, no ..). It is fixed at creation time; rename is not supported.

Sidecar shape

# vision-metadata.yml
title: Land the agentic decomposition ladder    # required
stage: draft                                    # required: draft | active

codex: main                                     # optional
severity: high                                  # optional priority hint
deadline: 2026-06-30                            # optional priority hint
decay: slow                                     # optional priority hint
complexity: medium                              # optional priority hint (sidecar-only)
resolution: patron retired the vision           # optional, used on terminal transitions

# Managed by `nsg vision apply` — do not edit by hand.
visionId: w-...                                 # written after first apply

| Field | Required | Notes | |---|---|---| | title | yes | Short human-readable title for the vision writ. | | stage | yes | Lifecycle stage. Allowed initial values are draft (writ phase new) and active (writ phase open). sunset and cancelled are rejected on first apply — a vision cannot be born retired; transition to a terminal stage on a later apply. | | codex | no | Target codex name for the vision. | | visionId | no, system-managed | Written by apply after first creation. Do not edit by hand. Clear the field only to deliberately re-create the vision (the old writ stays in place and becomes orphaned from this directory). | | severity | no | Priority hint surfaced in writ.ext['surveyor']. | | deadline | no | Priority hint surfaced in writ.ext['surveyor']. | | decay | no | Priority hint surfaced in writ.ext['surveyor']. | | complexity | no | Priority hint surfaced in writ.ext['surveyor']. Sidecar-only — there is no CLI flag for this field. | | resolution | no | Passed through to transitionVision on terminal moves. |

Unknown keys are logged as a warning and ignored (preserves forward-compatibility while still surfacing typos).

visionId binding

After the first successful nsg vision apply <slug>, the tool writes the new writ's id back into the sidecar as visionId. The yaml is round-tripped via parseDocument, so comments and key order survive the rewrite, and the file is replaced atomically (write-temp, rename-over) so a process crash cannot lose the binding.

On every subsequent apply the tool resolves the writ via visionId, updates writ.body from vision.md, and syncs stage/codex changes through the typed cartograph API. Edits to the writ are not propagated back to the file — the data flow is one-way (file → writ).

Stale-binding recovery

If the bound writ has been deleted, cancelled, completed, or failed, the next apply errors cleanly with no partial writes. To recover, either restore the writ to a non-terminal state, or clear the visionId field in the sidecar to let the next apply re-create the vision (the orphaned writ stays in place; nsg writ cancel it manually if needed).

Priority-hint semantics (ext['surveyor'])

Each apply writes a payload into writ.ext['surveyor'] carrying the fields enumerated above (severity, deadline, decay, complexity). CLI flags override sidecar values for the merged result:

# sidecar severity=low; CLI override wins
nsg vision apply my-vision --severity high

Fields that neither source provides are omitted from the payload. The slot is always written — even when the merged payload is {} — so its presence on the writ marks it as having been processed by the apply tool.

The slot's owner — a future surveyor-apparatus plugin that consumes these hints — does not yet ship. Until it does, the slot is inert; the key (surveyor) and the payload shape are load-bearing precedent for that future commission.

What is not in this commission

  • No vision-keeper agent runtime. vision-keeper.md is a placeholder stub; the agent runtime ships in a separate commission.
  • No per-type tree command. nsg writ tree --type vision already renders the writ-level shape; the cartograph-aware tree renderer (with stage badges per row) is a future commission.
  • No pages — the Oculus writs page auto-renders the new types via its type-vocabulary helper.
  • No link kinds — parent edges flow through writ.parentId. Typed link kinds are deferred.
  • No childrenBehavior cascade — patron-walkthrough semantics are coordinated by the typed API and downstream consumers.