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

@miadi/composition-to-episode

v0.2.0

Published

Studio compositions and chronicle episodes, related in both directions. Resolves a composition by portable ref (aureon/ava002) under $MIADI_STUDIO_DIR, weaves its provenance into an episode without ever rewriting the composition, and reads the link back —

Readme

@miadi/composition-to-episode

The migration weaver. This package reads a legacy gmtermux composition folder and weaves its provenance into a miadi-chronicle episode:

composition-to-episode weave <dir> --number N

The word "composition" in this package's name refers to the legacy source format — the gmtermux compositions*/ folder with its lazy composition.json manifest — not to the musical-composition studio domain. The studio domain lives at @miadi/musical-composition; the device act of capturing lives at @miadi/capture. This package is neither: it is the instrument that carries the old world into the new one.

Transitional, strangler-era

This is migration tooling. It exists because years of gmtermux compositions predate the chronicle and must cross over without being rewritten. It is the instrument that will execute the 74-row migration map ruled in the episode 318 vessel:

/srv/miadi/episodes/miadi-chronicle/2026-08-09-episode-318-a-folder-is-a-composition-the-capture-service-the-code-cannot-yet-hold/MIGRATION-MAP-compositions-to-chronicle-260809.md

When the corpus has crossed and the capture family owns new takes end-to-end, this package's work is done. It accretes no studio features and no capture features — a strangler-fig instrument, not a domain home.

The three roles, separated

Three roles were once entangled in @miadi/composition. They are now fully separate — otherwise, in the human's ruling, they "will always be confused":

| Role | Package | | --- | --- | | Studio artifact domain (key, capo, tempo, sections, chords) | @miadi/musical-composition | | Migration weaver (this package — transitional) | @miadi/composition-to-episode | | The device act of capturing | @miadi/capture, @miadi/capture-client |

The ownership split

| Concern | Owner | | --- | --- | | Creating and narrating episodes | passages | | Relating and syncing artefacts to episodes | @miadi/inquiry-weave | | Reading legacy compositions, authoring their provenance | @miadi/composition-to-episode | | Observing heterogeneous sources without judging them | @miadi/episodic-memory-schema |

The dependency runs one way. This package imports inquiry-weave and the schema; neither may ever import it. There is exactly one episode scaffold algorithm in this repository and it lives in inquiry-weave — every filesystem primitive on the episode side is delegated there.

What it will not do

  • Rewrite a composition. Reading is the only operation performed on a composition folder. No repair, no normalization, no schema-version stamping.
  • Invent an episode number. A slug reading ep250- is evidence about a recording, not authorization to claim episode 250. The number is offered as a candidate; a caller must confirm it.
  • Bump the weave version. weave: 1 is what every existing reader parses. Composition provenance travels in episode.yaml, never by versioning up.
  • Claim to be canonical. Everything projected is marked canonical: false. A machine-derived projection is a proposal to the chronicle, not a ruling.
  • Project to authored EpisodicMemory. That schema requires a session id, an opened-at, a charter purpose, and consent decisions. A composition supplies none of them, and inventing them would be authoring disguised as reading.

Classification, not validation

The composition corpus is deliberately heterogeneous — hand-authored folders sit beside editor-written ones and both are legitimate. A boolean valid/invalid would declare half the corpus broken, so compositions are classified:

| Classification | Meaning | | --- | --- | | current-ui-ready | Carries every collection the current editor writes | | compatible-legacy | Readable and whole, predating some of those collections | | repairable | Readable, with defects a human could resolve | | unsafe-or-ambiguous | Cannot be read, or its identity cannot be trusted |

A folder with no composition.json is compatible-legacy, not an error — the directory is the identity and the manifest materializes on the first edit.

Usage

A composition is addressed by what it is, not by where one machine keeps it: aureon/ava002, a bare slug searched across the shelves, or a path. Refs resolve under $MIADI_STUDIO_DIR.

composition-to-episode list                          # the whole studio, woven and unwoven
composition-to-episode list --unwoven --agent aureon # one shelf, only what no episode records
composition-to-episode linked                        # every recorded link, and whether it resolves here
composition-to-episode linked --episode 2026-08-17-episode-335-…

composition-to-episode observe  aureon/ava002        # read a composition, print its observation
composition-to-episode classify aureon/ava002        # classify it without touching it
composition-to-episode project  aureon/ava002        # print the episode.yaml overlay it would write
composition-to-episode weave    aureon/ava002 --number 336
composition-to-episode weave    aureon/ava002 --episode 335 --dry-run

list and linked both take --json, so a person and the chronicle app read the same answer out of the same code. linked exits 1 when any recorded link names a place this host cannot reach — see below.

The bin is named composition-to-episode, whole. The bare word composition belongs to the studio domain's future and is over-broad by ruling (rispecs/capture-vocabulary.spec.md §3) — this CLI never claims it.

import { readComposition, classifyComposition, weaveComposition } from "@miadi/composition-to-episode"

const source = await readComposition("/path/to/compositions-nyro/ep250-routing")
const assessment = classifyComposition(source)

const result = await weaveComposition({
  compositionDir: source.dir,
  number: 250,
  issue: "miadisabelle/gmtermux#31",
})

Environment

| Variable | Meaning | | --- | --- | | MIADI_STUDIO_DIR | The studio — agent shelves of compositions. Default /srv/miadi/episodes/miadi-studio | | MIADI_CHRONICLE_ROOT | Episode vessel root | | MIADI_INQUIRY_ROOT | Where artefact folders are resolved from | | MIADI_INQUIRY_REPO | Fallback repo for issue references |

MIADI_STUDIO_DIR is this package's own; the rest are inherited from @miadi/inquiry-weave, unchanged. Every chain is option, then environment, then a default literal at the end — never the other way around.

A composition folder anywhere on disk registers as an artefact by absolute path; it never has to be moved under the inquiry root.

Why the studio has a name

Before 0.2.0 a composition was addressed only by absolute path, and the projection recorded that path verbatim. Three episodes in the chronicle therefore carry

source_composition:
  path: /data/data/com.termux/files/home/compositions-nyro/ep097-ceremony-agent-skills

which is the Android device's own storage: true on exactly one machine, and that machine a phone. The work has since moved — captured on the device, dropped and committed into <studio>/<agent>/<composition>/ under the score/take custody law.

So source_composition now carries ref and studio_relative beside path, and the reader resolves the portable form against whatever $MIADI_STUDIO_DIR says on the host doing the reading. Existing blocks stay readable and are never rewritten; a link this host cannot follow reports resolvable: false rather than vanishing.

Reading the relation back

import {
  compositionsForEpisode,  // episode  -> the compositions it records
  readCompositionLinks,    // the whole chronicle, one pass
  studioWeaveStatus,       // studio   -> woven | unwoven
  resolveCompositionRef,   // "aureon/ava002" -> an absolute dir on this host
  listStudio,
} from "@miadi/composition-to-episode"

studioWeaveStatus matches by resolved absolute directory first — the only comparison two spellings of one path cannot fool — and falls back to the portable ref, so a link written on one host matches a folder read on another.

What gets written

Weaving writes three files, none of them inside the composition's manifest:

<composition>/.weave.yaml                     durable relation (weave: 1)
<composition>/AGENTS.md                       back-link appended
<episode>/inquiry/weave.yaml                  sync state (weave: 1)
<episode>/episode.yaml                        source_composition, projection, lineage

In episode.yaml, only source_composition, projection, and composition_musical are ever replaced. lineage is written only when absent — a hand-authored lineage always wins. Every other key is left exactly as found.

Requires

@miadi/episodic-memory-schema@^0.3.0 — 0.2.0 swept the songwriting layer into unmappedFields and labelled .mid and .mp4 clips as audio.

Provenance

This code was born as @miadi/composition, briefly carried the name @miadi/musical-composition (2026-08-09, same day), and settled here when the human ruled the three roles fully separate. The confession that named the entanglement — the founding wound — lives verbatim in the PROVENANCE section of packages/musical-composition/README.md, the studio domain home, where it was written.