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

@@ -1,9 +1,9 @@
import * as T from "../../../base/lib/types"
import * as child_process from "child_process"
import * as fs from "fs/promises"
import { Affine, asError } from "../util"
import { ExtendedVersion, VersionRange } from "../../../base/lib"
import { InitKind, InitScript } from "../../../base/lib/inits"
import * as T from '../../../base/lib/types'
import * as child_process from 'child_process'
import * as fs from 'fs/promises'
import { Affine, asError } from '../util'
import { ExtendedVersion, VersionRange } from '../../../base/lib'
import { InitKind, InitScript } from '../../../base/lib/inits'
export const DEFAULT_OPTIONS: T.SyncOptions = {
delete: true,
@@ -17,14 +17,14 @@ export type BackupSync<Volumes extends string> = {
restoreOptions?: Partial<T.SyncOptions>
}
export type BackupEffects = T.Effects & Affine<"Backups">
export type BackupEffects = T.Effects & Affine<'Backups'>
export class Backups<M extends T.SDKManifest> implements InitScript {
private constructor(
private options = DEFAULT_OPTIONS,
private restoreOptions: Partial<T.SyncOptions> = {},
private backupOptions: Partial<T.SyncOptions> = {},
private backupSet = [] as BackupSync<M["volumes"][number]>[],
private backupSet = [] as BackupSync<M['volumes'][number]>[],
private preBackup = async (effects: BackupEffects) => {},
private postBackup = async (effects: BackupEffects) => {},
private preRestore = async (effects: BackupEffects) => {},
@@ -32,7 +32,7 @@ export class Backups<M extends T.SDKManifest> implements InitScript {
) {}
static ofVolumes<M extends T.SDKManifest = never>(
...volumeNames: Array<M["volumes"][number]>
...volumeNames: Array<M['volumes'][number]>
): Backups<M> {
return Backups.ofSyncs(
...volumeNames.map((srcVolume) => ({
@@ -43,7 +43,7 @@ export class Backups<M extends T.SDKManifest> implements InitScript {
}
static ofSyncs<M extends T.SDKManifest = never>(
...syncs: BackupSync<M["volumes"][number]>[]
...syncs: BackupSync<M['volumes'][number]>[]
) {
return syncs.reduce((acc, x) => acc.addSync(x), new Backups<M>())
}
@@ -99,7 +99,7 @@ export class Backups<M extends T.SDKManifest> implements InitScript {
}
addVolume(
volume: M["volumes"][number],
volume: M['volumes'][number],
options?: Partial<{
options: T.SyncOptions
backupOptions: T.SyncOptions
@@ -113,7 +113,7 @@ export class Backups<M extends T.SDKManifest> implements InitScript {
})
}
addSync(sync: BackupSync<M["volumes"][0]>) {
addSync(sync: BackupSync<M['volumes'][0]>) {
this.backupSet.push(sync)
return this
}
@@ -136,15 +136,15 @@ export class Backups<M extends T.SDKManifest> implements InitScript {
const dataVersion = await effects.getDataVersion()
if (dataVersion)
await fs.writeFile("/media/startos/backup/dataVersion.txt", dataVersion, {
encoding: "utf-8",
await fs.writeFile('/media/startos/backup/dataVersion.txt', dataVersion, {
encoding: 'utf-8',
})
await this.postBackup(effects as BackupEffects)
return
}
async init(effects: T.Effects, kind: InitKind): Promise<void> {
if (kind === "restore") {
if (kind === 'restore') {
await this.restoreBackup(effects)
}
}
@@ -166,8 +166,8 @@ export class Backups<M extends T.SDKManifest> implements InitScript {
await rsyncResults.wait()
}
const dataVersion = await fs
.readFile("/media/startos/backup/dataVersion.txt", {
encoding: "utf-8",
.readFile('/media/startos/backup/dataVersion.txt', {
encoding: 'utf-8',
})
.catch((_) => null)
if (dataVersion) await effects.setDataVersion({ version: dataVersion })
@@ -189,23 +189,23 @@ async function runRsync(rsyncOptions: {
await fs.mkdir(dstPath, { recursive: true })
const command = "rsync"
const command = 'rsync'
const args: string[] = []
if (options.delete) {
args.push("--delete")
args.push('--delete')
}
for (const exclude of options.exclude) {
args.push(`--exclude=${exclude}`)
}
args.push("-rlptgocAXH")
args.push("--info=progress2")
args.push("--no-inc-recursive")
args.push('-rlptgocAXH')
args.push('--info=progress2')
args.push('--no-inc-recursive')
args.push(srcPath)
args.push(dstPath)
const spawned = child_process.spawn(command, args, { detached: true })
let percentage = 0.0
spawned.stdout.on("data", (data: unknown) => {
const lines = String(data).replace(/\r/g, "\n").split("\n")
spawned.stdout.on('data', (data: unknown) => {
const lines = String(data).replace(/\r/g, '\n').split('\n')
for (const line of lines) {
const parsed = /$([0-9.]+)%/.exec(line)?.[1]
if (!parsed) {
@@ -216,10 +216,10 @@ async function runRsync(rsyncOptions: {
}
})
let stderr = ""
let stderr = ''
spawned.stderr.on("data", (data: string | Buffer) => {
const errString = data.toString("utf-8")
spawned.stderr.on('data', (data: string | Buffer) => {
const errString = data.toString('utf-8')
stderr += errString
console.error(`Backups.runAsync`, asError(errString))
})
@@ -227,12 +227,12 @@ async function runRsync(rsyncOptions: {
const id = async () => {
const pid = spawned.pid
if (pid === undefined) {
throw new Error("rsync process has no pid")
throw new Error('rsync process has no pid')
}
return String(pid)
}
const waitPromise = new Promise<null>((resolve, reject) => {
spawned.on("exit", (code: any) => {
spawned.on('exit', (code: any) => {
if (code === 0) {
resolve(null)
} else {