agentleFS
sunholo-datasunholo-data/ailang/.agents/skills/ailang-packages/SKILL.md

ailang-packages

Skill38 starsChanged 9 days agoApache-2.0View on GitHub

Create, validate, and publish AILANG packages with correct conventions. Use when user asks to create a new package, fix package errors, add dependencies, publish to registry, or import packages. Also use when encountering IMP010, LDR001, MOD010, or export type errors during package development.

The file

We split this skill into the rules it gives an agent

6 rules. About 0 are common, 1 is distinctive, and 5 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 5

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Create, validate, and publish AILANG packages with correct conventions.

    line 8
  2. Very specific:

    Read ailang docs package-authoring first.

    line 21
  3. Very specific:

    Run ailang pkg quality --strict .

    line 35
  4. Very specific:

    If your project uses module myapp/...

    line 144
  5. Distinctive:

    If they conflict, the resolver fails (never silently downgrades)

    line 239
  6. Very specific:

    All modules pass: ailang check --package .

    line 263

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

AILANG Package Development

Create, validate, and publish AILANG packages with correct conventions. Use when user asks to create a new package, fix package errors, add dependencies, publish to registry, or import packages. Also use when encountering IMP010, LDR001, MOD010, or export type errors during package development.

When to Use This Skill

  • User wants to create a new AILANG package
  • User encounters package-related errors (IMP010, LDR001, MOD010, type unification across packages)
  • User asks about ailang.toml, ailang.lock, package imports, or package publishing
  • User wants to add dependencies between packages
  • User asks "how do I import from another package" or "how do I export types"
  • Code has import pkg/ or import ./ paths that aren't resolving

Start with the installed binary

Read ailang docs package-authoring first. If unavailable on an older binary, read the whole ailang prompt, including its contracts, testing and package sections. Use ailang docs --all-functions <term> and ailang pkg-docs --help before web search or guessing APIs. Verify historic limitations with a minimal reproducer against the installed version.

Native quality evidence

Separate pure logic from effectful adapters. Use ADTs for closed states/errors, meaningful requires/ensures for pure functions, boundary/invalid examples in native tests and properties for algebraic invariants. Declare minimal effect ceilings and bounded effect counts with @limit where meaningful. Never add vacuous contracts just to satisfy a count.

Run ailang pkg quality --strict . for the package quality report: compile, contracts, interface, effects, docs, style, and attested *_test.ail tests and smoke. It does not run inline test blocks in source modules, and it is not coverage or proof. Older binaries lacking this command require a manual evidence review; report that limitation explicitly.

ailang test --package . only discovers test.ail. Run source modules with inline tests explicitly (ailang test module.ail) too. A plain function named test is not a native test declaration. Report actual totals, failures and skips; zero discovered tests does not validate behavior. Use ailang verify --help for SMT verification and report proved/unknown/skipped outcomes separately.

Quick Reference

Create a Package

ailang init package --name vendor/name
ailang init package --name sunholo/mylib --module-prefix mylib --dep sunholo/config

Install Dependencies

ailang install sunholo/auth           # Install latest version (resolves from registry)
ailang install sunholo/auth@latest    # Same as above
ailang install sunholo/auth@0.1.0     # Install exact version

@latest resolves once and writes the exact version to ailang.toml. Semver ranges (^, ~, >=) are not supported — AILANG requires exact versions in manifests for determinism.

Package Lifecycle

ailang lock                    # Resolve dependencies → ailang.lock
ailang check --package .       # Type-check all modules (cross-module resolution)
ailang test --package .        # Run *_test.ail files
ailang pkg quality --strict .  # Inventory missing authoring evidence
ailang publish --dry-run       # Packaging preview, not remote validation or proof
ailang publish                 # Publish to registry

Critical Rules (learned from production)

1. Module names use underscores, never hyphens

Hyphens parse as subtraction. Directory names can have hyphens, but module paths must use underscores.

Directory:  packages/billing-store/
Module:     module sunholo/billing_store/customers_repo
Import:     import pkg/sunholo/billing_store/customers_repo (getCustomer)

2. Use ./ for intra-package sibling imports

Three-way import distinction — locality is explicit at the point of use:

import ./plan (Plan, lookupPlan)              -- LOCAL: sibling in same package
import pkg/sunholo/firestore/client (getDoc)  -- EXTERNAL: different package
import std/result (Ok, Err)                   -- STDLIB: bundled

./ resolves in module namespace (not filesystem): if current module is sunholo/billing_entitlements/entitlement, then ./plan normalizes to sunholo/billing_entitlements/plan.

import ./plan (Plan, lookupPlan, freePlan)    -- sibling
import ./sub/helpers (validate)               -- child directory

pkg/ self-imports also work (backward compatible) but ./ is preferred.

3. Cross-package types MUST use export type

Types used by other packages need export type, not just type. Without it, consumers get IMP010: symbol not exported.

-- WRONG: only visible within this module
type Customer = { name: string, email: string }

-- CORRECT: visible to importing packages
export type Customer = { name: string, email: string }

This applies to record types AND ADTs:

export type ProposalStatus = PendingApproval | AwaitingPayment | Approved
export type RequestedBy = Human | Agent(string)

4. Always import Ok and Err explicitly

They are NOT in the auto-imported prelude:

import std/result (Ok, Err)

5. Package name is vendor/name format (exactly 2 segments)

[package]
name = "sunholo/firestore"    # CORRECT
name = "firestore"            # WRONG — single segment
name = "sunholo/billing/store" # WRONG — 3 segments

6. Use module_prefix for existing apps adopting packages

If your project uses module myapp/... but you want to publish as sunholo/myapp:

[package]
name = "sunholo/myapp"
module_prefix = "myapp"

[exports]
modules = ["myapp/services/api", "myapp/handlers/parse"]

Zero source changes needed — existing module myapp/... declarations work as-is.

7. Publishing rewrites path deps automatically

ailang publish automatically rewrites path deps ({ path = "../firestore" }) to registry version strings ("0.1.0") in the tarball. Your local ailang.toml is restored after. You don't need to change deps manually before publishing.

Publish in dependency order: packages with no deps first, then packages that depend on already-published packages.

ailang.toml Reference

See resources/manifest_reference.md for full field documentation.

[package]
name = "sunholo/billing_store"
version = "0.2.0"
edition = "1"
ailang = ">=0.9.5"              # optional: minimum AILANG version
module_prefix = "myapp"         # optional: for existing apps
description = "Firestore CRUD for billing records"
license = "Apache-2.0"

[exports]
modules = [
  "sunholo/billing_store/customers_repo",
  "sunholo/billing_store/subscriptions_repo"
]

[dependencies]
# Path deps (local development):
"sunholo/firestore" = { path = "../firestore" }
# Git deps (version pinned):
# "sunholo/firestore" = { git = "https://github.com/sunholo-data/ailang-packages", subdir = "packages/firestore", tag = "main" }
# Registry deps (published packages — use exact versions only, no ranges):
# "sunholo/firestore" = "0.1.0"
# Install latest: ailang install sunholo/firestore

[effects]
max = ["Net", "FS", "Env"]     # effect ceiling — functions can't exceed this

[metadata]
tags = ["billing", "firestore"]
ai_summary = "Firestore CRUD for billing records"

[stability]
level = "experimental"          # experimental | stable | frozen

Lock File Portability

Registry and git lock entries resolve from the local cache (~/.ailang/cache/). Path dependencies are recorded relative to the depending ailang.toml (forward slashes), so a lock stays valid when the whole tree is cloned or moved — but only if the dependency is inside that tree (a sibling repo is not in a CI clone). ailang lock --check verifies the committed lock without writing; it flags a lock from an older ailang that still names an absolute path, and ailang lock rewrites it relative.

Docker workflow:

COPY ailang.toml ailang.lock .
RUN ailang install sunholo/auth    # Populates cache from lock file versions

Key facts:

  • Lock file stores: name, version, content hash, source type, git URL/rev
  • Registry/git entries do not need absolute cache paths; local path entries are workspace-specific
  • ailang install populates the cache; ailang lock resolves + downloads
  • Old lock files with stored paths still work (backward compatible)

Version Conflict Detection

The resolver enforces flat dependencies — one version per package name. If a transitive dependency requires a different version than the root manifest pins, ailang lock fails with a structured error:

version conflict: sunholo/firestore
  root requires: 0.2.0
  already resolved: 0.1.0
  transitive requires: 0.1.0 (via sunholo/billing_store)

resolution aborted

suggestion:
  - republish sunholo/billing_store against sunholo/firestore@0.2.0
  - or change root dependency to sunholo/firestore@0.1.0 explicitly

Resolution rules:

  • Direct dependencies in the root ailang.toml are authoritative
  • Transitive dependencies must match the direct pin exactly
  • If they conflict, the resolver fails (never silently downgrades)
  • Same version from multiple sources is fine (silently deduplicated)

How to fix version conflicts:

  1. Republish the transitive package against the version you need
  2. Or change your root ailang.toml to match the transitive version
  3. The error message tells you exactly which package introduced the conflict

Common Error Solutions

See resources/error_solutions.md for full troubleshooting guide.

ErrorCauseFix
version conflict: pkgDirect and transitive deps disagree on versionRepublish transitive dep or change root pin (see error message)
IMP010: symbol not exportedType missing export keywordAdd export type Foo = ...
LDR001: module not foundMissing dependency or wrong import pathAdd dep to ailang.toml + ailang lock
cannot unify type constructor X with TRecordType alias not exported across packagesAdd export type to the defining module
package not found in ailang.lockDependencies not resolvedRun ailang lock
PAR_HYPHEN_IN_MODULEHyphen in module pathUse underscores: billing_store not billing-store
Key has already been definedDuplicate dep entry in ailang.tomlRemove duplicate, keep one format

Publishing Checklist

  1. All modules pass: ailang check --package .
  2. Dependencies are listed in [dependencies] (path deps OK — publish rewrites them)
  3. Exported types have export type
  4. [exports].modules lists all public modules
  5. [effects].max includes all effects used
  6. AGENT.md exists with usage guide
  7. Native tests/properties have been executed with totals and skips reviewed; source inline tests run explicitly
  8. Meaningful contracts and effect budgets reviewed; proof outcomes recorded separately
  9. ailang pkg quality --strict . reports no missing evidence, or gaps are explicitly documented (do not claim the strict gate passed)
  10. Publish in dependency order (leaf packages first)

publish --dry-run returns before remote registry validation. It is packaging evidence, not a test or proof gate.

Registry Validator

The registry validator (/version endpoint shows deployed version):

  • Runs ailang check --package . on uploaded tarballs
  • Rewrites any remaining path deps to registry versions (safety net for older clients)
  • Runs ailang lock to download deps from registry before checking
  • Validates compilation, effect ceilings, and contracts

Workflow

  1. Read resources/manifest_reference.md for ailang.toml details
  2. Read resources/error_solutions.md when encountering errors
  3. Run scripts/validate_package.sh after creating a package
  4. Follow the critical rules above — they prevent the most common failures

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.