Skip to content

Latest commit

 

History

History
388 lines (296 loc) · 14.4 KB

File metadata and controls

388 lines (296 loc) · 14.4 KB

Contributing to Signet

This guide is for developers contributing to the signetai/ monorepo, the reference implementation of the Signet open standard.

New to git or GitHub? Start with Your First PR, a step-by-step walkthrough of making your first contribution.

This guide is for contributing from source. If you just want to use Signet as a product, follow Quickstart and install the global signet CLI instead of cloning the repo.

Development Setup

Contributor workflow, from source:

git clone https://github.com/Signet-AI/signetai.git
cd signetai
bun install
bun run build
bun test

Before submitting changes, run the full check suite:

bun run typecheck   # TypeScript strict mode check
bun run lint        # Biome static analysis
bun run format      # Biome auto-format
bun test            # All tests

Common local loops:

# Full workspace build
bun run build

# Daemon local dev
cd platform/daemon && bun run dev

# Website local dev
cd web/marketing && bun run dev

Project Structure

This is a Bun workspace monorepo organized by intent:

platform/               # engine/runtime: core, daemon, daemon-rs, predictor, native
surfaces/               # human-facing surfaces: CLI, dashboard, desktop, tray, browser extension
integrations/           # external harness integrations grouped by tool
libs/                   # reusable developer libraries: SDK, connector-base
plugins/                # Signet-native plugins loaded by Signet
dist/                   # assembled shipping artifacts, including signetai
runtimes/               # separate runtime ecosystems, currently Forge
web/                    # marketing site and Cloudflare workers
memorybench/            # benchmark harness, datasets, reports, and local UI

Key packages:

platform/core/                         # @signet/core — types, database, search, identity
platform/daemon/                       # @signet/daemon — HTTP API, file watcher, pipeline
platform/daemon-rs/                    # Rust shadow daemon/parity runtime
platform/predictor/                    # Rust predictive memory scorer sidecar
surfaces/cli/                          # @signet/cli — setup wizard and daemon management
surfaces/dashboard/                    # signet-dashboard — Svelte dashboard
surfaces/desktop/                      # @signet/desktop — Electron desktop application
surfaces/browser-extension/            # @signet/extension — browser extension
libs/sdk/                              # @signet/sdk — integration SDK for third-party apps
libs/connector-base/                   # @signet/connector-base — shared connector primitives
integrations/<tool>/connector/         # install-time harness connectors
integrations/<tool>/plugin/            # plugins loaded by external tools
integrations/openclaw/memory-adapter/  # @signetai/signet-memory-openclaw
plugins/core/secrets/                  # core Signet-native secrets plugin
dist/signetai/                         # signetai — installable distribution package
runtimes/forge/                        # Forge runtime ecosystem
web/marketing/                         # @signet/web — marketing site (Cloudflare Pages)
web/workers/reviews/                   # Cloudflare Worker for review automation
memorybench/                           # benchmark harness and benchmark UI

Key Modules

These are the areas most likely to be touched in non-trivial contributions. Familiarize yourself with them before diving in.

platform/daemon/src/pipeline/ is the LLM-based memory extraction pipeline. It runs in stages: extraction (extraction.ts, uses Ollama by default with qwen3:4b) → decision (decision.ts, write/update/skip) → optional graph operations → retention decay. The entrypoint is worker.ts; provider.ts wires up the stages. Config modes like shadowMode and mutationsFrozen are respected here. For live prompt checks against local Ollama models, see platform/daemon/src/pipeline/README.md.

platform/daemon/src/auth/ handles token-based auth for the HTTP API. Key files: middleware.ts (Hono middleware), tokens.ts (token lifecycle), policy.ts (access rules), rate-limiter.ts.

platform/daemon/src/connectors/ is the connector framework used by the daemon. registry.ts manages connector registration; filesystem.ts handles connector-driven file operations.

platform/daemon/src/analytics.ts, timeline.ts, and diagnostics.ts provide observability. Analytics tracks pipeline events; timeline records structured agent history; diagnostics exposes health and repair tooling. Tests live alongside each file.

platform/core/src/database.ts owns the SQLite schema and migrations. Any schema change must go through here. The wrapper supports both bun:sqlite (under Bun) and better-sqlite3 (under Node.js) via runtime detection.

Development Workflow

Make changes, rebuild the affected package, then test:

# Rebuild a single package
cd platform/daemon && bun run build

# Run a single test file
bun test platform/daemon/src/pipeline/worker.test.ts

# Full rebuild
bun run build

For daemon changes specifically:

cd platform/daemon
bun run dev           # watch mode
bun run start         # run directly without watch

The daemon serves its HTTP API on port 3850 by default. You can override with SIGNET_PORT, SIGNET_HOST, and SIGNET_PATH environment variables.

Conventions

Package manager: Bun everywhere. Do not use npm or pnpm.

Linting and formatting: Biome. Run bun run lint and bun run format before committing. CI will enforce this.

TypeScript: Strict mode is enforced by convention. Specifically: no any (use unknown with narrowing), no as casts (fix the types), no non-null assertions (!), explicit return types on all exported functions, readonly where mutation is not intended, as const unions over enum.

Commit messages: Conventional commits with a 50-character subject line and 72-character body width. Use imperative mood. Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert. Scope the subject to the package or area changed, e.g. feat(daemon): add rate limiting to auth middleware.

File size: Aim to keep files under ~700 LOC. Split or refactor when a file grows unwieldy, especially if it improves testability.

Comments: Explain why, not what. Self-explanatory code needs no inline narration; non-obvious logic or workarounds deserve a brief note.

Naming

Use single word names by default. Multi-word names only when a single word would be ambiguous. Reduce variable count by inlining values used once.

// Good
const foo = 1
function journal(dir: string) {}
const journal = await Bun.file(path.join(dir, "journal.json")).json()

// Bad
const fooBar = 1
function prepareJournal(dir: string) {}
const journalPath = path.join(dir, "journal.json")
const journal = await Bun.file(journalPath).json()

Destructuring

Avoid unnecessary destructuring. Use dot notation to preserve context.

// Good
obj.a
obj.b

// Bad
const { a, b } = obj

Variables

Prefer const over let. Use ternaries or early returns instead of reassignment.

// Good
const foo = condition ? 1 : 2

// Bad
let foo
if (condition) foo = 1
else foo = 2

Control Flow

Avoid else statements. Prefer early returns.

// Good
function foo() {
  if (condition) return 1
  return 2
}

// Bad
function foo() {
  if (condition) return 1
  else return 2
}

Pull Requests

Keep PRs focused. A PR that touches the pipeline, auth, and CLI in unrelated ways is harder to review and more likely to introduce regressions. If you are unsure whether an architectural change fits, open an issue first.

Before contributing a connector or adapter, look at how connector-claude-code or connector-openclaw are structured. Connectors are designed to be idempotent — safe to install multiple times. Follow that pattern.

PRs with UI changes (dashboard, web, extension) must include screenshots. No screenshots, no merge.

Be transparent about AI assistance in PRs where applicable. See the AI Policy for disclosure requirements and expectations.

Conventional Commits and Versioning

Commit types drive automated version bumps:

  • feat: or feat(scope):minor version bump (user-facing features only)
  • fix:, refactor:, chore:, perf:, docs:, etc. → patch bump
  • BREAKING CHANGE: in subject or ! after type (e.g. feat!:) → major bump

Use feat: only for genuinely new user-facing functionality. Internal improvements, helpers, and plumbing should use fix:, refactor:, chore:, or perf: to avoid unnecessary minor bumps.

Release Workflow

Releases are fully automated via GitHub Actions (.github/workflows/release.yml). Do not publish packages manually. Push to main and CI handles the rest.

What triggers a release

Every push to main triggers the workflow, unless the commit message contains chore: release (prevents infinite loops from release commits) or the push only changes non-code files (markdown, images, etc.).

Automated steps

  1. Buildbun install && bun run build on all packages
  2. Version bump — Reads the current version from dist/signetai/package.json, compares with remote, computes bump level from commit messages, and increments accordingly. All package.json files (except surfaces/dashboard/package.json) are updated to the new version.
  3. Changelogbun scripts/changelog.ts --bump-only computes the bump level from conventional commit subjects since the last tag, then bun scripts/changelog.ts --version <new-version> writes the matching CHANGELOG.md entry for the actual release version.
  4. npm publish — Publishes signetai and @signetai/signet-memory-openclaw to npm with the next tag, then promotes to latest (unless it's a major bump).
  5. Commit and tag — Commits the version bump and changelog as chore: release <version>, creates a v<version> git tag, and pushes both.
  6. GitHub Release — Creates a GitHub release with the changelog section as notes.

Published packages

  • signetai (meta-package bundling CLI + daemon)
  • @signetai/signet-memory-openclaw (OpenClaw runtime adapter)

Adding a new package to the publish step

Append an additional cd ../path && npm publish --tag next --access public line to the "Publish to npm" step in .github/workflows/release.yml, and add a corresponding npm dist-tag add in the "Promote to latest" step.

Scripts

All scripts live in scripts/ and are written in TypeScript (run via bun) or bash.

Script Description
changelog.ts Computes the semver bump from conventional commits since the last git tag, can prepend a CHANGELOG.md entry for an explicit release version, and can rebuild the full changelog from git tags. Generated entries include a short release summary, optional tag range, and grouped sections (feat, fix, perf, refactor, docs). Writes a .bump-level file used by CI to determine the semver bump. Called automatically during the release workflow.
bump-level.ts Exports computeBumpLevel() — scans commit subjects for BREAKING CHANGE: (→ major), feat: (→ minor), or defaults to patch. Used by changelog.ts.
version-sync.ts Aligns the version field in versioned Signet runtime/package workspaces to match the reference version in dist/signetai/package.json. Web manifests are intentionally excluded. Run manually with bun run version:sync or pass --to <version> to set an explicit version.
extract-changelog-section.ts Extracts a single version's section from CHANGELOG.md. Used by CI to populate GitHub release notes.
check-install-guide.ts Validates that the install guide (web/marketing/public/skill.md), README, and landing page components contain the expected install prompt and don't reference deprecated commands.
post-push-sync.sh Watches for the release workflow to complete after a push to main, then pulls the resulting release commit locally. Useful for staying in sync after pushing.

Identity Files

Signet recognizes these standard identity files at $SIGNET_WORKSPACE/:

File Required Description
AGENTS.md yes Operational rules and behavioral settings
SOUL.md yes Persona, character, and security settings
IDENTITY.md yes Agent name, creature type, and vibe
USER.md yes User profile and preferences
HEARTBEAT.md no Current working state, focus, and blockers
MEMORY.md no Memory index and summary
TOOLS.md no Tool preferences and notes
BOOTSTRAP.md no Setup ritual (typically deleted after first run)

The detectExistingSetup() function in platform/core/src/identity.ts detects existing setups from OpenClaw, Claude Code, and OpenCode.

Reference Repos

Use these as implementation references when designing protocol handling, integrations, and operational safeguards.

To run any script manually:

bun scripts/changelog.ts --bump-only
bun scripts/changelog.ts --version 1.2.3
bun scripts/changelog.ts --rebuild
bun scripts/version-sync.ts --to 1.2.3
bun scripts/extract-changelog-section.ts 0.14.5
bun scripts/check-install-guide.ts
./scripts/post-push-sync.sh

Test Discovery

Test discovery runs through workspace package scripts. Prefer targeted package tests or bun run --filter ... test over bare root bun test, since references/ contains third-party codebases with their own tests.

To run tests for a specific package:

# Run all tests in a package
bun test platform/daemon/

# Run a single test file
bun test platform/daemon/src/pipeline/worker.test.ts

# Run all tests across all workspaces
bun run test