From c3f02723193afe9c6ee52e3f95fb498cc8dcfdae Mon Sep 17 00:00:00 2001 From: TrueNine Date: Tue, 24 Mar 2026 03:27:54 +0800 Subject: [PATCH] Refactor release pipeline and CLI workspace integration --- .githooks/sync-versions.test.ts | 135 +++++++++++ .githooks/sync-versions.ts | 242 +++++++++++++++---- Cargo.toml | 2 +- cli/npm/darwin-arm64/package.json | 2 +- cli/npm/darwin-x64/package.json | 2 +- cli/npm/linux-arm64-gnu/package.json | 2 +- cli/npm/linux-x64-gnu/package.json | 2 +- cli/npm/win32-x64-msvc/package.json | 2 +- cli/package.json | 2 +- cli/src/plugins/CodexCLIOutputPlugin.test.ts | 29 +++ cli/src/plugins/CodexCLIOutputPlugin.ts | 20 +- doc/package.json | 2 +- gui/package.json | 2 +- gui/src-tauri/Cargo.toml | 2 +- gui/src-tauri/tauri.conf.json | 2 +- libraries/logger/package.json | 2 +- libraries/md-compiler/package.json | 2 +- libraries/script-runtime/package.json | 2 +- mcp/package.json | 2 +- package.json | 2 +- 20 files changed, 385 insertions(+), 73 deletions(-) create mode 100644 .githooks/sync-versions.test.ts diff --git a/.githooks/sync-versions.test.ts b/.githooks/sync-versions.test.ts new file mode 100644 index 00000000..2e8c6b69 --- /dev/null +++ b/.githooks/sync-versions.test.ts @@ -0,0 +1,135 @@ +import {execFileSync} from 'node:child_process' +import {mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync} from 'node:fs' +import {tmpdir} from 'node:os' +import {dirname, join} from 'node:path' +import {afterEach, describe, expect, it} from 'vitest' +import {runSyncVersions} from './sync-versions' + +function writeJson(filePath: string, value: Record): void { + mkdirSync(dirname(filePath), {recursive: true}) + writeFileSync(filePath, JSON.stringify(value, null, 2) + '\n', 'utf-8') +} + +function writeText(filePath: string, content: string): void { + mkdirSync(dirname(filePath), {recursive: true}) + writeFileSync(filePath, content, 'utf-8') +} + +function runGit(rootDir: string, args: readonly string[]): string { + return execFileSync('git', args, { + cwd: rootDir, + encoding: 'utf-8', + stdio: ['ignore', 'pipe', 'pipe'] + }).trim() +} + +function createFixtureRepo(): string { + const rootDir = mkdtempSync(join(tmpdir(), 'tnmsc-sync-versions-')) + const initialVersion = '2026.10324.10015' + + writeJson(join(rootDir, 'package.json'), { + name: '@truenine/memory-sync', + version: initialVersion + }) + writeJson(join(rootDir, 'cli', 'package.json'), { + name: '@truenine/memory-sync-cli', + version: initialVersion + }) + writeJson(join(rootDir, 'cli', 'npm', 'darwin-arm64', 'package.json'), { + name: '@truenine/memory-sync-cli-darwin-arm64', + version: initialVersion + }) + writeJson(join(rootDir, 'libraries', 'logger', 'package.json'), { + name: '@truenine/logger', + version: initialVersion + }) + writeText(join(rootDir, 'Cargo.toml'), [ + '[workspace]', + 'members = ["cli-crate"]', + '', + '[workspace.package]', + `version = "${initialVersion}"`, + '' + ].join('\n')) + writeText(join(rootDir, 'cli-crate', 'Cargo.toml'), [ + '[package]', + 'name = "cli-crate"', + `version = "${initialVersion}"`, + '' + ].join('\n')) + writeJson(join(rootDir, 'gui', 'src-tauri', 'tauri.conf.json'), { + version: initialVersion, + productName: 'Memory Sync' + }) + + runGit(rootDir, ['init']) + runGit(rootDir, ['config', 'user.email', 'codex@example.com']) + runGit(rootDir, ['config', 'user.name', 'Codex']) + runGit(rootDir, ['add', '.']) + runGit(rootDir, ['commit', '-m', 'initial']) + + return rootDir +} + +const tempDirs: string[] = [] + +afterEach(() => { + while (tempDirs.length > 0) { + const rootDir = tempDirs.pop() + if (rootDir != null) { + rmSync(rootDir, {recursive: true, force: true}) + } + } +}) + +describe('sync-versions hook', () => { + it('uses a staged package.json version as the sync source and stages all propagated changes', () => { + const rootDir = createFixtureRepo() + tempDirs.push(rootDir) + + const nextVersion = '2026.10324.10314' + writeJson(join(rootDir, 'cli', 'npm', 'darwin-arm64', 'package.json'), { + name: '@truenine/memory-sync-cli-darwin-arm64', + version: nextVersion + }) + runGit(rootDir, ['add', 'cli/npm/darwin-arm64/package.json']) + + const result = runSyncVersions({rootDir}) + const stagedFiles = new Set(runGit(rootDir, ['diff', '--cached', '--name-only']).split(/\r?\n/).filter(Boolean)) + + expect(result.targetVersion).toBe(nextVersion) + expect(result.versionSource).toBe('cli/npm/darwin-arm64/package.json') + expect(JSON.parse(readFileSync(join(rootDir, 'package.json'), 'utf-8')) as {version: string}).toMatchObject({version: nextVersion}) + expect(JSON.parse(readFileSync(join(rootDir, 'cli', 'package.json'), 'utf-8')) as {version: string}).toMatchObject({version: nextVersion}) + expect(JSON.parse(readFileSync(join(rootDir, 'libraries', 'logger', 'package.json'), 'utf-8')) as {version: string}).toMatchObject({version: nextVersion}) + expect(readFileSync(join(rootDir, 'Cargo.toml'), 'utf-8')).toContain(`version = "${nextVersion}"`) + expect(readFileSync(join(rootDir, 'cli-crate', 'Cargo.toml'), 'utf-8')).toContain(`version = "${nextVersion}"`) + expect(JSON.parse(readFileSync(join(rootDir, 'gui', 'src-tauri', 'tauri.conf.json'), 'utf-8')) as {version: string}).toMatchObject({version: nextVersion}) + expect(stagedFiles).toEqual(new Set([ + 'Cargo.toml', + 'cli-crate/Cargo.toml', + 'cli/npm/darwin-arm64/package.json', + 'cli/package.json', + 'gui/src-tauri/tauri.conf.json', + 'libraries/logger/package.json', + 'package.json' + ])) + }) + + it('fails when staged package.json files propose conflicting versions', () => { + const rootDir = createFixtureRepo() + tempDirs.push(rootDir) + + writeJson(join(rootDir, 'cli', 'npm', 'darwin-arm64', 'package.json'), { + name: '@truenine/memory-sync-cli-darwin-arm64', + version: '2026.10324.10314' + }) + writeJson(join(rootDir, 'libraries', 'logger', 'package.json'), { + name: '@truenine/logger', + version: '2026.10324.10315' + }) + runGit(rootDir, ['add', 'cli/npm/darwin-arm64/package.json', 'libraries/logger/package.json']) + + expect(() => runSyncVersions({rootDir})).toThrowError(/Conflicting staged package\.json versions detected/) + }) +}) diff --git a/.githooks/sync-versions.ts b/.githooks/sync-versions.ts index bc46fa4c..256f4058 100644 --- a/.githooks/sync-versions.ts +++ b/.githooks/sync-versions.ts @@ -3,18 +3,29 @@ * Version Sync Script * Auto-sync all publishable package versions before commit. */ +import {execFileSync} from 'node:child_process' import {readdirSync, readFileSync, writeFileSync} from 'node:fs' -import {join, relative, resolve} from 'node:path' +import {basename, join, relative, resolve} from 'node:path' import process from 'node:process' +import {pathToFileURL} from 'node:url' interface VersionedJson { version?: string [key: string]: unknown } -const ROOT_DIR = resolve('.') -const ROOT_PACKAGE_PATH = resolve(ROOT_DIR, 'package.json') -const ROOT_CARGO_PATH = resolve(ROOT_DIR, 'Cargo.toml') +export interface SyncVersionsOptions { + readonly requestedVersion?: string + readonly rootDir?: string +} + +export interface SyncVersionsResult { + readonly changedPaths: readonly string[] + readonly rootDir: string + readonly targetVersion: string + readonly versionSource: string +} + const IGNORED_DIRECTORIES = new Set([ '.git', '.next', @@ -24,6 +35,7 @@ const IGNORED_DIRECTORIES = new Set([ 'node_modules', 'target', ]) +const CALVER_VERSION_REGEX = /^\d{4}\.(?:0|1\d{2}(?:\d{2})?)\.(?:0|1\d{2}(?:\d{2}(?:\d{2})?)?)$/u function readJsonFile(filePath: string): VersionedJson { return JSON.parse(readFileSync(filePath, 'utf-8').replace(/^\uFEFF/, '')) as VersionedJson @@ -102,101 +114,229 @@ function updateVersionLineInSection( return content } +function runGit(rootDir: string, args: readonly string[]): string { + return execFileSync('git', args, { + cwd: rootDir, + encoding: 'utf-8', + stdio: ['ignore', 'pipe', 'pipe'] + }).trim() +} + +function validateVersion(version: string, source: string): void { + if (!CALVER_VERSION_REGEX.test(version)) { + throw new Error(`Invalid CalVer version in ${source}: ${version}`) + } +} + function syncJsonVersion( filePath: string, - rootVersion: string, + targetVersion: string, changedPaths: Set, ): void { try { const json = readJsonFile(filePath) - if (json.version === rootVersion) { + if (json.version === targetVersion) { return } - console.log(` ✓ ${relative(ROOT_DIR, filePath)}: version ${String(json.version ?? '(none)')} -> ${rootVersion}`) - json.version = rootVersion + json.version = targetVersion writeJsonFile(filePath, json) changedPaths.add(filePath) } catch { - console.log(`⚠️ ${relative(ROOT_DIR, filePath)} not found or invalid, skipping`) + console.log(`⚠️ ${filePath} not found or invalid, skipping`) } } function syncCargoVersion( filePath: string, sectionName: string, - rootVersion: string, + targetVersion: string, changedPaths: Set, ): void { try { const originalContent = readFileSync(filePath, 'utf-8') - const updatedContent = updateVersionLineInSection(originalContent, sectionName, rootVersion) + const updatedContent = updateVersionLineInSection(originalContent, sectionName, targetVersion) if (updatedContent === originalContent) { return } writeFileSync(filePath, updatedContent, 'utf-8') - console.log(` ✓ ${relative(ROOT_DIR, filePath)}: version -> ${rootVersion}`) changedPaths.add(filePath) } catch { - console.log(`⚠️ ${relative(ROOT_DIR, filePath)} not found or invalid, skipping`) + console.log(`⚠️ ${filePath} not found or invalid, skipping`) } } -const requestedVersion = process.argv[2]?.trim() -const rootPkg = readJsonFile(ROOT_PACKAGE_PATH) -const changedPaths = new Set() +function getStagedPackageVersionCandidates(rootDir: string, rootVersion: string): Map { + const stagedFiles = runGit(rootDir, ['diff', '--cached', '--name-only', '--diff-filter=ACMR']) + .split(/\r?\n/) + .map(line => line.trim()) + .filter(line => line.length > 0) + .filter(filePath => basename(filePath) === 'package.json') -if (requestedVersion && rootPkg.version !== requestedVersion) { - rootPkg.version = requestedVersion - writeJsonFile(ROOT_PACKAGE_PATH, rootPkg) - changedPaths.add(ROOT_PACKAGE_PATH) -} + const candidates = new Map() -const rootVersion = rootPkg.version + for (const relativePath of stagedFiles) { + const stagedContent = runGit(rootDir, ['show', `:${relativePath}`]) + const json = JSON.parse(stagedContent.replace(/^\uFEFF/, '')) as VersionedJson + const version = typeof json.version === 'string' ? json.version.trim() : '' -if (rootVersion == null || rootVersion === '') { - console.error('Root package.json missing version field') - process.exit(1) -} + if (version.length === 0 || version === rootVersion) { + continue + } + + validateVersion(version, `${relativePath} (staged)`) -console.log(`🔄 Syncing version: ${rootVersion}`) + const existingPaths = candidates.get(version) + if (existingPaths == null) { + candidates.set(version, [relativePath]) + continue + } -const packageJsonPaths = discoverFilesByName(ROOT_DIR, 'package.json') - .filter(filePath => resolve(filePath) !== ROOT_PACKAGE_PATH) - .sort() + existingPaths.push(relativePath) + } -for (const filePath of packageJsonPaths) { - syncJsonVersion(filePath, rootVersion, changedPaths) + return candidates } -syncCargoVersion(ROOT_CARGO_PATH, 'workspace.package', rootVersion, changedPaths) +function resolveTargetVersion( + rootDir: string, + rootVersion: string, + requestedVersion?: string, +): {readonly version: string, readonly source: string} { + if (requestedVersion != null && requestedVersion !== '') { + validateVersion(requestedVersion, 'requested version') + return { + version: requestedVersion, + source: 'command argument' + } + } + + const candidates = getStagedPackageVersionCandidates(rootDir, rootVersion) + const versions = [...candidates.keys()] + + if (versions.length === 0) { + validateVersion(rootVersion, 'root package.json') + return { + version: rootVersion, + source: 'root package.json' + } + } + + if (versions.length > 1) { + const details = versions + .sort() + .map(version => `${version}: ${candidates.get(version)?.sort().join(', ') ?? ''}`) + .join('; ') + throw new Error(`Conflicting staged package.json versions detected: ${details}`) + } + + const [version] = versions + const sourcePaths = candidates.get(version) ?? [] + + return { + version, + source: sourcePaths.sort().join(', ') + } +} -const cargoTomlPaths = discoverFilesByName(ROOT_DIR, 'Cargo.toml') - .filter(filePath => resolve(filePath) !== ROOT_CARGO_PATH) - .sort() +function stageFiles(rootDir: string, filePaths: readonly string[]): void { + if (filePaths.length === 0) { + return + } -for (const filePath of cargoTomlPaths) { - syncCargoVersion(filePath, 'package', rootVersion, changedPaths) + runGit(rootDir, ['add', '--', ...filePaths.map(filePath => relative(rootDir, filePath))]) } -for (const filePath of discoverFilesByName(ROOT_DIR, 'tauri.conf.json').sort()) { - syncJsonVersion(filePath, rootVersion, changedPaths) +export function runSyncVersions(options: SyncVersionsOptions = {}): SyncVersionsResult { + const rootDir = resolve(options.rootDir ?? '.') + const rootPackagePath = resolve(rootDir, 'package.json') + const rootCargoPath = resolve(rootDir, 'Cargo.toml') + const rootPkg = readJsonFile(rootPackagePath) + const currentRootVersion = typeof rootPkg.version === 'string' ? rootPkg.version.trim() : '' + + if (currentRootVersion === '') { + throw new Error('Root package.json missing version field') + } + + validateVersion(currentRootVersion, 'root package.json') + + const target = resolveTargetVersion(rootDir, currentRootVersion, options.requestedVersion?.trim()) + const changedPaths = new Set() + + if (rootPkg.version !== target.version) { + rootPkg.version = target.version + writeJsonFile(rootPackagePath, rootPkg) + changedPaths.add(rootPackagePath) + } + + const packageJsonPaths = discoverFilesByName(rootDir, 'package.json') + .filter(filePath => resolve(filePath) !== rootPackagePath) + .sort() + + for (const filePath of packageJsonPaths) { + syncJsonVersion(filePath, target.version, changedPaths) + } + + syncCargoVersion(rootCargoPath, 'workspace.package', target.version, changedPaths) + + const cargoTomlPaths = discoverFilesByName(rootDir, 'Cargo.toml') + .filter(filePath => resolve(filePath) !== rootCargoPath) + .sort() + + for (const filePath of cargoTomlPaths) { + syncCargoVersion(filePath, 'package', target.version, changedPaths) + } + + for (const filePath of discoverFilesByName(rootDir, 'tauri.conf.json').sort()) { + syncJsonVersion(filePath, target.version, changedPaths) + } + + stageFiles(rootDir, [...changedPaths].sort()) + + return { + changedPaths: [...changedPaths].sort(), + rootDir, + targetVersion: target.version, + versionSource: target.source + } } -if (changedPaths.size === 0) { - console.log('\n✅ All versions consistent, no update needed') - process.exit(0) +function shouldRunAsCli(entryPath: string | undefined): boolean { + if (entryPath == null || entryPath === '') { + return false + } + + return import.meta.url === pathToFileURL(resolve(entryPath)).href } -const changedRelativePaths = [...changedPaths] - .map(filePath => relative(ROOT_DIR, filePath)) - .sort() +function main(): number { + try { + const requestedVersion = process.argv[2]?.trim() + const result = runSyncVersions({requestedVersion}) + + console.log(`🔄 Syncing version: ${result.targetVersion}`) + console.log(` source: ${result.versionSource}`) + + if (result.changedPaths.length === 0) { + console.log('\n✅ All versions consistent, no update needed') + return 0 + } + + console.log('\n✅ Synced and staged version updates:') + for (const filePath of result.changedPaths) { + console.log(` - ${relative(result.rootDir, filePath)}`) + } + + return 0 + } catch (error) { + const message = error instanceof Error ? error.message : String(error) + console.error(`\n❌ ${message}`) + return 1 + } +} -console.error('\n❌ Versions were out of sync. Updated files:') -for (const relativePath of changedRelativePaths) { - console.error(` - ${relativePath}`) +if (shouldRunAsCli(process.argv[1])) { + process.exit(main()) } -console.error('\nReview these changes and rerun the commit.') -process.exit(1) diff --git a/Cargo.toml b/Cargo.toml index 6c66ecec..4ca06e65 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ members = [ ] [workspace.package] -version = "2026.10324.10015" +version = "2026.10324.10325" edition = "2024" license = "AGPL-3.0-only" authors = ["TrueNine"] diff --git a/cli/npm/darwin-arm64/package.json b/cli/npm/darwin-arm64/package.json index 4541f255..675732ab 100644 --- a/cli/npm/darwin-arm64/package.json +++ b/cli/npm/darwin-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-cli-darwin-arm64", - "version": "2026.10324.10015", + "version": "2026.10324.10325", "os": [ "darwin" ], diff --git a/cli/npm/darwin-x64/package.json b/cli/npm/darwin-x64/package.json index f697687f..e22bdc40 100644 --- a/cli/npm/darwin-x64/package.json +++ b/cli/npm/darwin-x64/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-cli-darwin-x64", - "version": "2026.10324.10015", + "version": "2026.10324.10325", "os": [ "darwin" ], diff --git a/cli/npm/linux-arm64-gnu/package.json b/cli/npm/linux-arm64-gnu/package.json index 146ef40a..35c6064d 100644 --- a/cli/npm/linux-arm64-gnu/package.json +++ b/cli/npm/linux-arm64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-cli-linux-arm64-gnu", - "version": "2026.10324.10015", + "version": "2026.10324.10325", "os": [ "linux" ], diff --git a/cli/npm/linux-x64-gnu/package.json b/cli/npm/linux-x64-gnu/package.json index dd97dba9..3ad2f63b 100644 --- a/cli/npm/linux-x64-gnu/package.json +++ b/cli/npm/linux-x64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-cli-linux-x64-gnu", - "version": "2026.10324.10015", + "version": "2026.10324.10325", "os": [ "linux" ], diff --git a/cli/npm/win32-x64-msvc/package.json b/cli/npm/win32-x64-msvc/package.json index 8e0199cd..ff461e83 100644 --- a/cli/npm/win32-x64-msvc/package.json +++ b/cli/npm/win32-x64-msvc/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-cli-win32-x64-msvc", - "version": "2026.10324.10015", + "version": "2026.10324.10325", "os": [ "win32" ], diff --git a/cli/package.json b/cli/package.json index 7a992591..7b403886 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,7 +1,7 @@ { "name": "@truenine/memory-sync-cli", "type": "module", - "version": "2026.10324.10015", + "version": "2026.10324.10325", "description": "TrueNine Memory Synchronization CLI", "author": "TrueNine", "license": "AGPL-3.0-only", diff --git a/cli/src/plugins/CodexCLIOutputPlugin.test.ts b/cli/src/plugins/CodexCLIOutputPlugin.test.ts index 91e4f2f7..09e4cd37 100644 --- a/cli/src/plugins/CodexCLIOutputPlugin.test.ts +++ b/cli/src/plugins/CodexCLIOutputPlugin.test.ts @@ -116,6 +116,18 @@ function createProjectCommandPrompt(): CommandPrompt { } as CommandPrompt } +function createCommandPromptWithToolFields(): CommandPrompt { + return { + ...createProjectCommandPrompt(), + yamlFrontMatter: { + description: 'Tool-aware command', + scope: 'project', + allowTools: ['shell'], + allowedTools: ['shell'] + } as unknown as CommandPrompt['yamlFrontMatter'] + } as CommandPrompt +} + function createSubAgentPrompt(scope: 'project' | 'global'): SubAgentPrompt { return { type: PromptKind.SubAgent, @@ -218,6 +230,23 @@ describe('codexCLIOutputPlugin command output', () => { }) }) + it('drops tool allowlist fields from codex command front matter', async () => { + await withTempCodexDirs('tnmsc-codex-command-tools', async ({workspace, homeDir}) => { + const plugin = new TestCodexCLIOutputPlugin(homeDir) + const writeCtx = createWriteContext(workspace, [createCommandPromptWithToolFields()]) + const declarations = await plugin.declareOutputFiles(writeCtx) + const declaration = declarations.find(item => item.path === path.join(homeDir, '.codex', 'prompts', 'dev-build.md')) + + expect(declaration).toBeDefined() + if (declaration == null) throw new Error('Expected codex command declaration') + + const rendered = await plugin.convertContent(declaration, writeCtx) + expect(String(rendered)).toContain('description: Tool-aware command') + expect(String(rendered)).not.toContain('allowTools') + expect(String(rendered)).not.toContain('allowedTools') + }) + }) + it('writes project-scoped subagents into each project .codex/agents directory as toml', async () => { await withTempCodexDirs('tnmsc-codex-project-subagent', async ({workspace, homeDir}) => { const plugin = new TestCodexCLIOutputPlugin(homeDir) diff --git a/cli/src/plugins/CodexCLIOutputPlugin.ts b/cli/src/plugins/CodexCLIOutputPlugin.ts index 2b43cb8c..ca4236cd 100644 --- a/cli/src/plugins/CodexCLIOutputPlugin.ts +++ b/cli/src/plugins/CodexCLIOutputPlugin.ts @@ -8,16 +8,24 @@ const AGENTS_SUBDIR = 'agents' const CODEX_SUBAGENT_FIELD_ORDER = ['name', 'description', 'developer_instructions'] as const const CODEX_EXCLUDED_SUBAGENT_FIELDS = ['scope', 'seriName', 'argumentHint', 'color', 'namingCase', 'model'] as const -function transformCodexSubAgentFrontMatter( - subAgentCanonicalName: string, +function sanitizeCodexFrontMatter( sourceFrontMatter?: Record ): Record { const frontMatter = {...sourceFrontMatter} - frontMatter['name'] = subAgentCanonicalName - // Codex agent role deserialization currently rejects `allowedTools`. - // Keep accepting upstream `allowTools` metadata for other outputs, but drop it here for Codex TOML compatibility. + // Codex front matter rejects tool allowlists. Keep accepting upstream metadata + // for other outputs, but drop both common spellings here for Codex compatibility. delete frontMatter['allowTools'] + delete frontMatter['allowedTools'] + return frontMatter +} + +function transformCodexSubAgentFrontMatter( + subAgentCanonicalName: string, + sourceFrontMatter?: Record +): Record { + const frontMatter = sanitizeCodexFrontMatter(sourceFrontMatter) + frontMatter['name'] = subAgentCanonicalName return frontMatter } @@ -29,7 +37,7 @@ const CODEX_OUTPUT_OPTIONS = { scopeRemap: { project: 'global' }, - transformFrontMatter: (_cmd, context) => context.sourceFrontMatter ?? {} + transformFrontMatter: (_cmd, context) => sanitizeCodexFrontMatter(context.sourceFrontMatter) }, subagents: { subDir: AGENTS_SUBDIR, diff --git a/doc/package.json b/doc/package.json index c63e242d..9afc469f 100644 --- a/doc/package.json +++ b/doc/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-docs", - "version": "2026.10324.10015", + "version": "2026.10324.10325", "private": true, "description": "Chinese-first manifesto-led documentation site for @truenine/memory-sync.", "engines": { diff --git a/gui/package.json b/gui/package.json index 1cf05d5e..fd3ce60f 100644 --- a/gui/package.json +++ b/gui/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-gui", - "version": "2026.10324.10015", + "version": "2026.10324.10325", "private": true, "engines": { "node": ">=25.2.1", diff --git a/gui/src-tauri/Cargo.toml b/gui/src-tauri/Cargo.toml index 78bb4718..a57d5782 100644 --- a/gui/src-tauri/Cargo.toml +++ b/gui/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "memory-sync-gui" -version = "2026.10324.10015" +version = "2026.10324.10325" description = "Memory Sync desktop GUI application" authors.workspace = true edition.workspace = true diff --git a/gui/src-tauri/tauri.conf.json b/gui/src-tauri/tauri.conf.json index 07fb2ef2..4bd3d760 100644 --- a/gui/src-tauri/tauri.conf.json +++ b/gui/src-tauri/tauri.conf.json @@ -1,6 +1,6 @@ { "$schema": "https://schema.tauri.app/config/2", - "version": "2026.10324.10015", + "version": "2026.10324.10325", "productName": "Memory Sync", "identifier": "org.truenine.memory-sync", "build": { diff --git a/libraries/logger/package.json b/libraries/logger/package.json index 43cbdef1..0a2492ca 100644 --- a/libraries/logger/package.json +++ b/libraries/logger/package.json @@ -1,7 +1,7 @@ { "name": "@truenine/logger", "type": "module", - "version": "2026.10324.10015", + "version": "2026.10324.10325", "private": true, "description": "Rust-powered structured logger for Node.js via N-API", "license": "AGPL-3.0-only", diff --git a/libraries/md-compiler/package.json b/libraries/md-compiler/package.json index e66768ed..5599f81d 100644 --- a/libraries/md-compiler/package.json +++ b/libraries/md-compiler/package.json @@ -1,7 +1,7 @@ { "name": "@truenine/md-compiler", "type": "module", - "version": "2026.10324.10015", + "version": "2026.10324.10325", "private": true, "description": "Rust-powered MDX→Markdown compiler for Node.js with pure-TS fallback", "license": "AGPL-3.0-only", diff --git a/libraries/script-runtime/package.json b/libraries/script-runtime/package.json index 4b2bc4cd..b695e349 100644 --- a/libraries/script-runtime/package.json +++ b/libraries/script-runtime/package.json @@ -1,7 +1,7 @@ { "name": "@truenine/script-runtime", "type": "module", - "version": "2026.10324.10015", + "version": "2026.10324.10325", "private": true, "description": "Rust-backed TypeScript proxy runtime for tnmsc", "license": "AGPL-3.0-only", diff --git a/mcp/package.json b/mcp/package.json index 773241be..add45a60 100644 --- a/mcp/package.json +++ b/mcp/package.json @@ -1,7 +1,7 @@ { "name": "@truenine/memory-sync-mcp", "type": "module", - "version": "2026.10324.10015", + "version": "2026.10324.10325", "description": "MCP stdio server for managing memory-sync prompt sources and translation artifacts", "author": "TrueNine", "license": "AGPL-3.0-only", diff --git a/package.json b/package.json index 9270ca3f..061f3428 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync", - "version": "2026.10324.10015", + "version": "2026.10324.10325", "description": "Cross-AI-tool prompt synchronisation toolkit (CLI + Tauri desktop GUI) — one ruleset, multi-target adaptation. Monorepo powered by pnpm + Turbo.", "license": "AGPL-3.0-only", "keywords": [