add documentation for ai agents (#3115)

* add documentation for ai agents

* docs: consolidate CLAUDE.md and CONTRIBUTING.md, add style guidelines

- Refactor CLAUDE.md to reference CONTRIBUTING.md for build/test/format info
- Expand CONTRIBUTING.md with comprehensive build targets, env vars, and testing
- Add code style guidelines section with conventional commits
- Standardize SDK prettier config to use single quotes (matching web)
- Add project-level Claude Code settings to disable co-author attribution

* style(sdk): apply prettier with single quotes

Run prettier across sdk/base and sdk/package to apply the
standardized quote style (single quotes matching web).

* docs: add USER.md for per-developer TODO filtering

- Add agents/USER.md to .gitignore (contains user identifier)
- Document session startup flow in CLAUDE.md:
  - Create USER.md if missing, prompting for identifier
  - Filter TODOs by @username tags
  - Offer relevant TODOs on session start

* docs: add i18n documentation task to agent TODOs

* docs: document i18n ID patterns in core/

Add agents/i18n-patterns.md covering rust-i18n setup, translation file
format, t!() macro usage, key naming conventions, and locale selection.
Remove completed TODO item and add reference in CLAUDE.md.

* chore: clarify that all builds work on any OS with Docker
This commit is contained in:
Aiden McClelland
2026-02-06 00:10:16 +01:00
committed by GitHub
parent 86ca23c093
commit f2142f0bb3
280 changed files with 6793 additions and 5515 deletions

View File

@@ -4,11 +4,11 @@ import {
Manifest,
MerkleArchiveCommitment,
PackageId,
} from "../osBindings"
import { ArrayBufferReader, MerkleArchive } from "./merkleArchive"
import mime from "mime"
import { DirectoryContents } from "./merkleArchive/directoryContents"
import { FileContents } from "./merkleArchive/fileContents"
} from '../osBindings'
import { ArrayBufferReader, MerkleArchive } from './merkleArchive'
import mime from 'mime'
import { DirectoryContents } from './merkleArchive/directoryContents'
import { FileContents } from './merkleArchive/fileContents'
const magicAndVersion = new Uint8Array([59, 59, 2])
@@ -37,12 +37,12 @@ export class S9pk {
)
const magicVersion = new Uint8Array(header.next(magicAndVersion.length))
if (!compare(magicVersion, magicAndVersion)) {
throw new Error("Invalid Magic or Unexpected Version")
throw new Error('Invalid Magic or Unexpected Version')
}
const archive = await MerkleArchive.deserialize(
source,
"s9pk",
's9pk',
header,
commitment,
)
@@ -50,7 +50,7 @@ export class S9pk {
const manifest = JSON.parse(
new TextDecoder().decode(
await archive.contents
.getPath(["manifest.json"])
.getPath(['manifest.json'])
?.verifiedFileContents(),
),
)
@@ -60,24 +60,24 @@ export class S9pk {
async icon(): Promise<DataUrl> {
const iconName = Object.keys(this.archive.contents.contents).find(
(name) =>
name.startsWith("icon.") && mime.getType(name)?.startsWith("image/"),
name.startsWith('icon.') && mime.getType(name)?.startsWith('image/'),
)
if (!iconName) {
throw new Error("no icon found in archive")
throw new Error('no icon found in archive')
}
return (
`data:${mime.getType(iconName)};base64,` +
Buffer.from(
await this.archive.contents.getPath([iconName])!.verifiedFileContents(),
).toString("base64")
).toString('base64')
)
}
async dependencyMetadataFor(id: PackageId) {
const entry = this.archive.contents.getPath([
"dependencies",
'dependencies',
id,
"metadata.json",
'metadata.json',
])
if (!entry) return null
return JSON.parse(
@@ -86,18 +86,18 @@ export class S9pk {
}
async dependencyIconFor(id: PackageId) {
const dir = this.archive.contents.getPath(["dependencies", id])
const dir = this.archive.contents.getPath(['dependencies', id])
if (!dir || !(dir.contents instanceof DirectoryContents)) return null
const iconName = Object.keys(dir.contents.contents).find(
(name) =>
name.startsWith("icon.") && mime.getType(name)?.startsWith("image/"),
name.startsWith('icon.') && mime.getType(name)?.startsWith('image/'),
)
if (!iconName) return null
return (
`data:${mime.getType(iconName)};base64,` +
Buffer.from(
await dir.contents.getPath([iconName])!.verifiedFileContents(),
).toString("base64")
).toString('base64')
)
}
@@ -120,9 +120,9 @@ export class S9pk {
}
async license(): Promise<string> {
const file = this.archive.contents.getPath(["LICENSE.md"])
const file = this.archive.contents.getPath(['LICENSE.md'])
if (!file || !(file.contents instanceof FileContents))
throw new Error("license.md not found in archive")
throw new Error('license.md not found in archive')
return new TextDecoder().decode(await file.verifiedFileContents())
}
}