Files
ocas/CLAUDE.md
T
xiaoju b43bbef80f chore: update release scripts and CLAUDE.md
- prepare-release.sh: delete consumed changesets from main after branching
- publish.sh: add --rc flag for prerelease (rc.N, auto-increment)
- publish.sh: auto-fix workspace:* and version in all packages
- publish.sh: auto-restore workspace:* on main after final release
- CLAUDE.md: document changeset-on-main, prerelease, and final release flows
2026-06-02 00:14:07 +00:00

5.6 KiB

CLAUDE.md — OCAS

Object Content Addressable Store — self-describing CAS with JSON Schema typed nodes.

Project Structure

Monorepo with 3 packages under packages/:

Package Directory Description
@ocas/core packages/core Core CAS engine — hashing, schema, store, verify, bootstrap
@ocas/fs packages/fs Filesystem-backed CAS store
@ocas/cli packages/cli CLI tool (ocas binary)

Tech Stack

  • Runtime: Bun
  • Language: TypeScript (strict mode, exactOptionalPropertyTypes, noUncheckedIndexedAccess)
  • Build: tsc --build (composite project references)
  • Test: bun test
  • Lint/Format: Biome (biome check . / biome format --write .)
  • Publish: Changesets + bun publish → npmjs (@ocas/*)

Commands

bun test          # Run all tests
bun run build     # Build all packages
bun run check     # Biome lint
bun run format    # Biome format (auto-fix)

Code Conventions

TypeScript

  • Strict mode — no any, no unchecked index access, no implicit overrides
  • verbatimModuleSyntax — use import type for type-only imports
  • Import paths — use .js extension in imports (ESM convention with bundler resolution)
  • Export style — named exports only, re-export from index.ts

Biome Rules

  • noConsole: "error" globally (except packages/cli)
  • Recommended ruleset enabled
  • Auto-organize imports via assist.actions.source.organizeImports
  • Indent: 2 spaces

Naming

  • Types: PascalCase (CasNode, Hash, Store)
  • Functions: camelCase (computeHash, createMemoryStore)
  • Constants: UPPER_SNAKE_CASE (BOOTSTRAP_STORE)
  • Files: kebab-case.ts
  • Test files: co-located as *.test.ts

Key Types

  • Hash — 13-character uppercase Crockford Base32 string (XXH64)
  • CasNode — content-addressed node with schema
  • Store — abstract storage interface (get/put)
  • VariableStore — SQLite-backed mutable bindings (name → hash)
  • ListOptions — sorting/pagination options (sort, desc, limit, offset)
  • ListEntry — list result entry (hash, created, updated)

List Utilities

packages/core/src/list-utils.ts provides applyListOptions() — in-memory sort/paginate for ListEntry[] arrays. Used by MemoryStore; FsStore pushes sort/limit to SQLite. Core layer treats limit: undefined as "no limit"; the CLI defaults to 100 in parseListOptions().

Architecture Notes

  • No "alias" concept — every name resolution flows through the VariableStore. Builtin schemas (@ocas/schema, @ocas/string, @ocas/output/*, …) are registered as variables during bootstrap(store, varStore), alongside user-defined variables created via ocas var set.
  • bootstrap(store, varStore?) writes builtin name → hash bindings into the varStore when one is provided; called automatically by openStore() and openStoreAndVarStore().
  • resolveHash(input, varStore) is the unified hash/name resolver in the CLI. If input matches the 13-char hash format it is returned as-is; otherwise the varStore is queried by exact name. This means every CLI command that accepts a hash argument also accepts a variable name (schema names, user vars, etc.).
  • Variable naming: all names must follow @scope/name format (@[a-zA-Z][a-zA-Z0-9]*/segments). @ocas/* is reserved for builtins. The @ prefix ensures names are visually distinct from hashes.
  • openStoreAndVarStore() in the CLI opens both stores and bootstraps once; prefer it over separate openStore() + createVariableStore() to avoid double bootstrap.

Internal Dependencies

Workspace packages reference each other with workspace:* in package.json. This is resolved to real version numbers only during publishing (see below).

Git

  • Commit format: type: description (conventional commits)
  • Reference issues: Fixes #N / Closes #N
  • Author: 小橘 <xiaoju@shazhou.work>

Project Rules

Before Submitting

  1. bun test — all tests pass
  2. bun run check — no lint errors
  3. bun run build — builds cleanly

Release Process

Releases use a release branch workflow. main always keeps workspace:* for internal dependencies; version numbers are only fixed on the release branch.

Adding a Changeset

Add changesets alongside feature PRs on main:

bunx changeset        # interactive — pick packages + bump type + summary

Changesets live in .changeset/ as markdown files until consumed by prepare-release.sh.

Prepare

./scripts/prepare-release.sh

This script:

  1. Checks you're on main with a clean tree and pending changesets
  2. Creates release/<version> branch
  3. Runs changeset version to fix versions and generate CHANGELOGs
  4. Switches back to main and deletes consumed .changeset/*.md files
  5. Runs full validation (install, build, lint, test) on the release branch
  6. Commits the version bump

After preparation, review changes and fix any issues on the release branch.

Prerelease

./scripts/publish.sh --rc

Publishes <version>-rc.N with npm tag rc. Auto-increments the rc number. Install for testing: bun add -g @ocas/cli@rc

Final Release

./scripts/publish.sh

This script:

  1. Validates you're on a release/* branch with no pending changesets
  2. Sets the final version, fixes workspace:* → real versions
  3. Runs final build + test
  4. Publishes packages in order: @ocas/core@ocas/fs@ocas/cli
  5. Tags, pushes to origin + github
  6. Merges back to main, restores workspace:*, cleans up release branch