Merge origin/master at f1402327fa
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
|
||||
import { existsSync, readdirSync, readFileSync } from 'node:fs'
|
||||
import { join, relative, resolve } from 'node:path'
|
||||
import { isForbiddenPublicationFile } from './publication-payload.ts'
|
||||
import { hasTypeRTRemoteNavigation, isForbiddenPublicationFile } from './publication-payload.ts'
|
||||
|
||||
const root = resolve(import.meta.dirname, '..')
|
||||
// vendor/* is single-level; packages/<group>/<pkg> nests one level deeper
|
||||
@@ -122,6 +122,7 @@ function sameStringList(actual: readonly string[] | undefined, expected: readonl
|
||||
|
||||
function expectedDshPackageFiles(manifest: PackageManifest): readonly string[] {
|
||||
const extras = manifest.name ? packageFileExtras[manifest.name] ?? [] : []
|
||||
const typeRTRemoteNavigation = hasTypeRTRemoteNavigation(manifest)
|
||||
return [
|
||||
'lib/index.js',
|
||||
// Every package publishes its invariant ownership companion as a separate
|
||||
@@ -145,9 +146,37 @@ function expectedDshPackageFiles(manifest: PackageManifest): readonly string[] {
|
||||
// declarations.
|
||||
...usesEmittedTreeDefaults(manifest) ? ['lib/types/**/*.js'] : [],
|
||||
'lib/types/**/*.d.ts',
|
||||
...hasExportPair(manifest, './typert', './lib/typert.host.d.ts', './lib/typert.host.js')
|
||||
? ['lib/typert.host.js', 'lib/typert.host.d.ts']
|
||||
: [],
|
||||
...hasExportPair(manifest, './client/typert', './lib/typert.client.d.ts', './lib/typert.client.js')
|
||||
? ['lib/typert.client.js', 'lib/typert.client.d.ts']
|
||||
: [],
|
||||
...typeRTRemoteNavigation
|
||||
? [
|
||||
'lib/typert.remote-client.js',
|
||||
'lib/typert.remote-client.d.ts',
|
||||
'lib/typert.remote-client.d.ts.map',
|
||||
'src',
|
||||
]
|
||||
: [],
|
||||
]
|
||||
}
|
||||
|
||||
/** Whether one conditional export exactly names the generated runtime and declaration pair. */
|
||||
function hasExportPair(
|
||||
manifest: PackageManifest,
|
||||
subpath: string,
|
||||
types: string,
|
||||
runtime: string,
|
||||
): boolean {
|
||||
const entry = manifest.exports?.[subpath]
|
||||
return typeof entry === 'object'
|
||||
&& entry !== null
|
||||
&& entry.types === types
|
||||
&& entry.default === runtime
|
||||
}
|
||||
|
||||
/** Runtime target of an export entry: conditional `default`, or the bare-string shorthand. */
|
||||
function exportDefault(manifest: PackageManifest, subpath: string): string | undefined {
|
||||
const entry = manifest.exports?.[subpath]
|
||||
@@ -175,8 +204,9 @@ function checkWorkspace({ dir, manifest }: WorkspaceManifest): string[] {
|
||||
}
|
||||
|
||||
if (manifest.name?.startsWith('@deepseek-ai/')) {
|
||||
const publicationPolicy = { typeRTRemoteNavigation: hasTypeRTRemoteNavigation(manifest) }
|
||||
for (const file of manifest.files ?? []) {
|
||||
if (isForbiddenPublicationFile(file)) {
|
||||
if (isForbiddenPublicationFile(file, publicationPolicy)) {
|
||||
errors.push(`${label}: package.json files must not publish ${JSON.stringify(file)}`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,13 @@ describe('client bundle purity gate', () => {
|
||||
expect(resolveId('@deepseek-ai/dsh-brand')).toBeNull()
|
||||
})
|
||||
|
||||
it('lets exact generated Remote contributions inline without admitting their package implementation', () => {
|
||||
expect(resolveId('@deepseek-ai/dsh-goal/remote')).toBeNull()
|
||||
expect(() => resolveId('@deepseek-ai/dsh-goal')).toThrow(/purity/)
|
||||
expect(() => resolveId('@deepseek-ai/dsh-goal/client')).toThrow(/purity/)
|
||||
expect(() => resolveId('@deepseek-ai/dsh-goal/remote/nested')).toThrow(/purity/)
|
||||
})
|
||||
|
||||
it('throws on any other @deepseek-ai leak', () => {
|
||||
expect(() => resolveId('@deepseek-ai/dsh-agent')).toThrow(/purity/)
|
||||
expect(() => resolveId('@deepseek-ai/dsh-client-web')).toThrow(/purity/)
|
||||
|
||||
@@ -22,13 +22,7 @@ export default defineConfig({
|
||||
const bundlePath = join(root, 'lib/client.js')
|
||||
await writeFile(sourcePath, 'export const version = "watch-v1"\n')
|
||||
bundles = await watchClientPlugins(root, ['.'], 50)
|
||||
await expect.poll(async () => {
|
||||
try {
|
||||
return (await readFile(bundlePath, 'utf8')).includes('watch-v1')
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}, { timeout: 10_000 }).toBe(true)
|
||||
expect(await readFile(bundlePath, 'utf8')).toContain('watch-v1')
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 1_000))
|
||||
await writeFile(sourcePath, `export const version = "watch-v2-${'x'.repeat(100)}"\n`)
|
||||
|
||||
@@ -47,21 +47,40 @@ export function discoverPluginDirs(root = repoRoot): string[] {
|
||||
* @param root - repository or fixture root passed to tsdown.
|
||||
* @param pluginDirs - workspace-relative package directories to watch.
|
||||
* @param pollInterval - optional source-watcher polling interval in milliseconds.
|
||||
* @returns live bundles whose async disposers stop every watcher.
|
||||
* @returns live bundles after every watcher has completed its initial build.
|
||||
*/
|
||||
export async function watchClientPlugins(
|
||||
root: string,
|
||||
pluginDirs: readonly string[],
|
||||
pollInterval?: number,
|
||||
): Promise<TsdownBundle[]> {
|
||||
return build({
|
||||
let resolveInitialBuilds: (() => void) | undefined
|
||||
const initialBuilds = new Promise<void>((resolve) => { resolveInitialBuilds = resolve })
|
||||
const initialized = new WeakSet<object>()
|
||||
const readiness: { expectedBuilds?: number; initializedBuilds: number } = { initializedBuilds: 0 }
|
||||
const bundles = await build({
|
||||
cwd: root,
|
||||
workspace: [...pluginDirs],
|
||||
watch: true,
|
||||
hooks: {
|
||||
'build:done': ({ options }) => {
|
||||
if (initialized.has(options)) return
|
||||
initialized.add(options)
|
||||
readiness.initializedBuilds += 1
|
||||
if (
|
||||
readiness.expectedBuilds !== undefined
|
||||
&& readiness.initializedBuilds >= readiness.expectedBuilds
|
||||
) resolveInitialBuilds?.()
|
||||
},
|
||||
},
|
||||
...pollInterval !== undefined
|
||||
? { inputOptions: { watch: { watcher: { usePolling: true, pollInterval } } } }
|
||||
: {},
|
||||
})
|
||||
readiness.expectedBuilds = bundles.length
|
||||
if (readiness.initializedBuilds >= readiness.expectedBuilds) resolveInitialBuilds?.()
|
||||
await initialBuilds
|
||||
return bundles
|
||||
}
|
||||
|
||||
const invokedPath = process.argv[1]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"AGENTS.md": 1775,
|
||||
"AGENTS.md": 1782,
|
||||
"docs/AGENTS.md": 1320,
|
||||
"docs/architecture.md": 2160,
|
||||
"docs/cordis-primer.md": 600,
|
||||
@@ -7,5 +7,5 @@
|
||||
"docs/testing.md": 1150,
|
||||
"examples/AGENTS.md": 310,
|
||||
"packages/AGENTS.md": 675,
|
||||
"packages/README.md": 920
|
||||
"packages/README.md": 936
|
||||
}
|
||||
|
||||
@@ -126,12 +126,13 @@ function loadFile(abs: string, rel: string, cache: Map<string, FileCtx>): FileCt
|
||||
}
|
||||
|
||||
/** A type declaration a paste can contain. */
|
||||
type TypeDecl = ts.InterfaceDeclaration | ts.TypeAliasDeclaration
|
||||
type TypeDecl = ts.InterfaceDeclaration | ts.TypeAliasDeclaration | ts.EnumDeclaration
|
||||
|
||||
/** Find an interface/type-alias declaration by name in a file, or null. */
|
||||
/** Find a pasteable type declaration by name in a file, or null. */
|
||||
function findTypeDecl(ctx: FileCtx, name: string): TypeDecl | null {
|
||||
for (const stmt of ctx.sf.statements) {
|
||||
if ((ts.isInterfaceDeclaration(stmt) || ts.isTypeAliasDeclaration(stmt)) && stmt.name.text === name) return stmt
|
||||
if ((ts.isInterfaceDeclaration(stmt) || ts.isTypeAliasDeclaration(stmt) || ts.isEnumDeclaration(stmt))
|
||||
&& stmt.name.text === name) return stmt
|
||||
}
|
||||
return null
|
||||
}
|
||||
@@ -207,7 +208,7 @@ function checkMemberDocs(ctx: FileCtx, decl: TypeDecl, violations: string[]): vo
|
||||
else ts.forEachChild(type, (n) => { walkNested(n, path) })
|
||||
}
|
||||
if (ts.isInterfaceDeclaration(decl)) walkMembers(decl.members, decl.name.text)
|
||||
else walkNested(decl.type, decl.name.text)
|
||||
else if (ts.isTypeAliasDeclaration(decl)) walkNested(decl.type, decl.name.text)
|
||||
}
|
||||
|
||||
/** Cross-file resolution context for the schema-path check. */
|
||||
|
||||
@@ -90,6 +90,7 @@ export const LINK_MAP: Readonly<Record<string, string>> = {
|
||||
FsWriteIntent: 'filesystem.md',
|
||||
FsWriteOutcome: 'filesystem.md',
|
||||
CreateGoalRequest: 'goal.md',
|
||||
CreateGoalResult: 'goal.md',
|
||||
EditGoalRequest: 'goal.md',
|
||||
GoalBlockReason: 'goal.md',
|
||||
GoalChanged: 'goal.md',
|
||||
@@ -276,6 +277,7 @@ export const TYPE_LINK_EXEMPTIONS: Readonly<Record<string, string>> = {
|
||||
TypertPackageRecord: 'registry package record is owned by packages/typert/registry/README.md',
|
||||
TypertSchemaFilter: 'registry schema query filter is owned by packages/typert/registry/README.md',
|
||||
TypertSchemaRecord: 'registry schema record is owned by packages/typert/registry/README.md',
|
||||
TypeRTDisposer: 'TypeRT lifecycle contract is owned by packages/typert/type-meta/README.md',
|
||||
'z.core.JSONSchema.BaseSchema': 'zod projection output is owned by the zod v4 API',
|
||||
'z.core.ToJSONSchemaParams': 'zod projection parameters are owned by the zod v4 API',
|
||||
InvariantInstaller: 'service-local contribution contract is owned by packages/support/invariants/README.md',
|
||||
@@ -287,6 +289,7 @@ export const TYPE_LINK_EXEMPTIONS: Readonly<Record<string, string>> = {
|
||||
ThemeTokens: 'service-local token dictionary is owned by packages/client/ui-theme/src/index.ts',
|
||||
Translate: 'service-local bound translator is owned by packages/client/i18n/src/index.ts',
|
||||
InvariantRegistration: 'service-local lifecycle handle is owned by packages/support/invariants/README.md',
|
||||
InvokeRemoteRequest: 'gateway invocation contract is owned by packages/api/gateway/README.md',
|
||||
PresetOption: 'deployment menu metadata is owned by packages/ui/permission/README.md',
|
||||
PresetSpec: 'deployment preset composition is owned by packages/ui/permission/README.md',
|
||||
KnobState: 'projection unit state shape is owned by packages/ui/permission/README.md',
|
||||
|
||||
@@ -140,8 +140,15 @@ const SERVICE_ROLES: ServiceRole[] = [
|
||||
pkg: 'typert-registry',
|
||||
title: 'Runtime type registry',
|
||||
mode: 'core',
|
||||
consumers: ['typert-loader'],
|
||||
note: 'Plugins register live zod contributions directly or through dsh-typert-loader; runtime consumers query schemas and reflection metadata at their own edges.',
|
||||
consumers: ['typert-loader', 'api-gateway'],
|
||||
note: 'Plugins register live zod contributions directly or through dsh-typert-loader; the API gateway consumes invocation descriptors and providers, while other runtime consumers query schemas and reflection metadata at their own edges.',
|
||||
},
|
||||
{
|
||||
key: 'typertGateway',
|
||||
pkg: 'api-gateway',
|
||||
title: 'TypeRT Host invocation gateway',
|
||||
mode: 'core',
|
||||
note: 'Associates generated Remote descriptors with live Cordis services, resolves registered identities, and exposes unary calls through the shared Connection RPC carrier.',
|
||||
},
|
||||
{
|
||||
key: 'sessionPersistence',
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { isForbiddenPublicationFile, validateTarballPayload } from './publication-payload.ts'
|
||||
import {
|
||||
hasTypeRTRemoteNavigation,
|
||||
isForbiddenPublicationFile,
|
||||
validateTarballPayload,
|
||||
} from './publication-payload.ts'
|
||||
|
||||
function validateFixtureTarball(files: readonly string[]): () => void {
|
||||
return () => {
|
||||
@@ -51,4 +55,29 @@ describe('publication payload policy', () => {
|
||||
'package/lib/styles/base.css',
|
||||
])).not.toThrow()
|
||||
})
|
||||
|
||||
it('allows only the TypeRT declaration map and its navigable source tree when requested', () => {
|
||||
const policy = { typeRTRemoteNavigation: true }
|
||||
expect(isForbiddenPublicationFile('src/index.ts', policy)).toBe(false)
|
||||
expect(isForbiddenPublicationFile('lib/typert.remote-client.d.ts.map', policy)).toBe(false)
|
||||
expect(isForbiddenPublicationFile('lib/types/index.d.ts.map', policy)).toBe(true)
|
||||
expect(() => {
|
||||
validateTarballPayload([
|
||||
'package/lib/typert.remote-client.d.ts.map',
|
||||
'package/src/index.ts',
|
||||
], 'fixture.tgz', policy)
|
||||
}).not.toThrow()
|
||||
})
|
||||
|
||||
it('recognizes only the canonical Host-for-Client export pair', () => {
|
||||
expect(hasTypeRTRemoteNavigation({
|
||||
exports: {
|
||||
'./remote': {
|
||||
types: './lib/typert.remote-client.d.ts',
|
||||
default: './lib/typert.remote-client.js',
|
||||
},
|
||||
},
|
||||
})).toBe(true)
|
||||
expect(hasTypeRTRemoteNavigation({ exports: { './remote': './lib/remote.js' } })).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
/** Publication payload policy shared by static manifests and packed tarballs. */
|
||||
|
||||
/** Publication exceptions required for TypeRT declaration-map navigation. */
|
||||
export interface PublicationPayloadPolicy {
|
||||
readonly typeRTRemoteNavigation?: boolean
|
||||
}
|
||||
|
||||
/** Whether a package manifest exports generated Host-for-Client metadata with source navigation. */
|
||||
export function hasTypeRTRemoteNavigation(manifest: unknown): boolean {
|
||||
if (manifest === null || typeof manifest !== 'object' || Array.isArray(manifest)) return false
|
||||
const exportsField = (manifest as Record<string, unknown>).exports
|
||||
if (exportsField === null || typeof exportsField !== 'object' || Array.isArray(exportsField)) return false
|
||||
const remote = (exportsField as Record<string, unknown>)['./remote']
|
||||
if (remote === null || typeof remote !== 'object' || Array.isArray(remote)) return false
|
||||
const entry = remote as Record<string, unknown>
|
||||
return entry.types === './lib/typert.remote-client.d.ts'
|
||||
&& entry.default === './lib/typert.remote-client.js'
|
||||
}
|
||||
|
||||
/** Normalize a package manifest path or npm tarball member to its payload-relative path. */
|
||||
function payloadPath(file: string): string {
|
||||
const normalized = file.replaceAll('\\', '/').replace(/^\.\/+/, '').replace(/\/+$/, '')
|
||||
@@ -7,17 +24,30 @@ function payloadPath(file: string): string {
|
||||
}
|
||||
|
||||
/** Whether a package payload path exposes source or declaration-map intermediates. */
|
||||
export function isForbiddenPublicationFile(file: string): boolean {
|
||||
export function isForbiddenPublicationFile(
|
||||
file: string,
|
||||
policy: PublicationPayloadPolicy = {},
|
||||
): boolean {
|
||||
const normalized = payloadPath(file)
|
||||
if (policy.typeRTRemoteNavigation === true
|
||||
&& (normalized === 'src'
|
||||
|| normalized.startsWith('src/')
|
||||
|| normalized === 'lib/typert.remote-client.d.ts.map')) {
|
||||
return false
|
||||
}
|
||||
return normalized === 'src'
|
||||
|| normalized.startsWith('src/')
|
||||
|| normalized.endsWith('.d.ts.map')
|
||||
}
|
||||
|
||||
/** Reject source and declaration-map members in a packed npm tarball. */
|
||||
export function validateTarballPayload(files: readonly string[], context: string): void {
|
||||
export function validateTarballPayload(
|
||||
files: readonly string[],
|
||||
context: string,
|
||||
policy: PublicationPayloadPolicy = {},
|
||||
): void {
|
||||
for (const file of files) {
|
||||
if (!isForbiddenPublicationFile(file)) continue
|
||||
if (!isForbiddenPublicationFile(file, policy)) continue
|
||||
const normalized = payloadPath(file)
|
||||
if (normalized === 'src' || normalized.startsWith('src/')) {
|
||||
throw new Error(`${context} publishes source file ${file}`)
|
||||
|
||||
@@ -18,7 +18,7 @@ import { basename, dirname, isAbsolute, join, normalize, relative, resolve, sep
|
||||
import { createInterface } from 'node:readline/promises'
|
||||
import { pathToFileURL } from 'node:url'
|
||||
import { parseArgs } from 'node:util'
|
||||
import { validateTarballPayload } from './publication-payload.ts'
|
||||
import { hasTypeRTRemoteNavigation, validateTarballPayload } from './publication-payload.ts'
|
||||
|
||||
const DEFAULT_REGISTRY = 'https://registry.npm.harnessment.com'
|
||||
const DEFAULT_OUTPUT_DIRECTORY = '.artifacts/npm-baseline'
|
||||
@@ -320,7 +320,11 @@ class ReleaseBundle {
|
||||
if (expected === undefined || !missingNames.delete(artifact.name)) {
|
||||
throw new Error(`unexpected or duplicate packed package: ${artifact.name}`)
|
||||
}
|
||||
if (expected.origin === 'harness') validateTarballPayload(artifact.files, tarball)
|
||||
if (expected.origin === 'harness') {
|
||||
validateTarballPayload(artifact.files, tarball, {
|
||||
typeRTRemoteNavigation: hasTypeRTRemoteNavigation(artifact.manifest),
|
||||
})
|
||||
}
|
||||
if (artifact.version !== version) {
|
||||
throw new Error(`${tarball} has version ${artifact.version}; expected ${version}`)
|
||||
}
|
||||
@@ -394,7 +398,11 @@ class ReleaseBundle {
|
||||
throw new Error(`tarball checksum mismatch: ${pkg.tarball}`)
|
||||
}
|
||||
const artifact = inspectTarball(path, runner)
|
||||
if (pkg.origin === 'harness') validateTarballPayload(artifact.files, pkg.tarball)
|
||||
if (pkg.origin === 'harness') {
|
||||
validateTarballPayload(artifact.files, pkg.tarball, {
|
||||
typeRTRemoteNavigation: hasTypeRTRemoteNavigation(artifact.manifest),
|
||||
})
|
||||
}
|
||||
if (artifact.name !== pkg.name || artifact.version !== this.manifest.version) {
|
||||
throw new Error(`tarball identity mismatch: ${pkg.tarball}`)
|
||||
}
|
||||
@@ -463,13 +471,6 @@ class InstalledBundleSmoke {
|
||||
+ `expected ${this.bundle.manifest.version}`,
|
||||
)
|
||||
}
|
||||
const config = this.runner.capture(
|
||||
process.execPath,
|
||||
[bin, '--dump-default-config'],
|
||||
consumerRoot,
|
||||
environment,
|
||||
)
|
||||
if (config === '') throw new Error('installed dsh --dump-default-config returned no output')
|
||||
this.probeWeb(bin, consumerRoot, environment)
|
||||
console.log('publish-npm-baseline: installed dsh entry and Web startup probes passed')
|
||||
} finally {
|
||||
|
||||
@@ -224,6 +224,7 @@ export function gatesForMode(selected: Mode): Gate[] {
|
||||
pnpmScript('cordis-config', 'verify-cordis-config', { label: 'Cordis config' }),
|
||||
pnpmScript('client-domain-graph', 'verify-client-domain-graph', { label: 'client domain graph' }),
|
||||
pnpmScript('test', 'test'),
|
||||
pnpmScript('issue-management', 'test:issue-management', { label: 'Issue management policy' }),
|
||||
pnpmScript('duplication', 'duplication'),
|
||||
snapshotGate(),
|
||||
pnpmScript('build', 'build'),
|
||||
@@ -240,12 +241,19 @@ export function gatesForMode(selected: Mode): Gate[] {
|
||||
}
|
||||
}
|
||||
|
||||
function ciPrimaryGates(): Gate[] {
|
||||
function ciSharedStaticGates(): Gate[] {
|
||||
return [
|
||||
pnpmScript('runtime-closure', 'verify-runtime-closure', { label: 'runtime closure' }),
|
||||
pnpmScript('constraints', 'constraints'),
|
||||
pnpmScript('package-invariants', 'verify-package-invariants', { label: 'package invariants' }),
|
||||
pnpmScript('cordis-config', 'verify-cordis-config', { label: 'Cordis config' }),
|
||||
pnpmScript('issue-management', 'test:issue-management', { label: 'Issue management policy' }),
|
||||
]
|
||||
}
|
||||
|
||||
function ciPrimaryGates(): Gate[] {
|
||||
return [
|
||||
...ciSharedStaticGates(),
|
||||
pnpmScript('typecheck', 'typecheck'),
|
||||
lintGate(),
|
||||
pnpmScript('duplication', 'duplication'),
|
||||
@@ -339,10 +347,7 @@ function runningNodeMajor(): number {
|
||||
|
||||
function ciStaticGates(options: { ownsBuild: boolean }): Gate[] {
|
||||
return [
|
||||
pnpmScript('runtime-closure', 'verify-runtime-closure', { label: 'runtime closure' }),
|
||||
pnpmScript('constraints', 'constraints'),
|
||||
pnpmScript('package-invariants', 'verify-package-invariants', { label: 'package invariants' }),
|
||||
pnpmScript('cordis-config', 'verify-cordis-config', { label: 'Cordis config' }),
|
||||
...ciSharedStaticGates(),
|
||||
...options.ownsBuild ? [pnpmScript('build', 'build')] : [],
|
||||
...docSyncLeafGates({
|
||||
includeDocTypecheck: options.ownsBuild,
|
||||
@@ -602,6 +607,7 @@ function builtBinSmokeGate(needs: string[] = ['build']): Gate {
|
||||
'packages/ui/jsonrpc/tests/built-scope-carrier.e2e.ts',
|
||||
'packages/subagent/subagent-codex/tests/loader-composition.e2e.ts',
|
||||
'packages/subagent/subagent-claude-code/tests/loader-composition.e2e.ts',
|
||||
'packages/api/remotes/tests/built-lib.e2e.ts',
|
||||
// The worker-entry packages' built bundles: the only automated proof
|
||||
// that lib/index.js resolves its sibling lib/worker.cjs under plain node
|
||||
// (the e2e lane runs unbuilt, so these files self-skip there).
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -199,7 +199,7 @@
|
||||
{
|
||||
"doc": "docs/core-data-structures/goal.md",
|
||||
"symbol": "GoalView",
|
||||
"source": "packages/goal/goal/src/domain.ts"
|
||||
"source": "packages/goal/goal/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/goal.md",
|
||||
@@ -219,12 +219,12 @@
|
||||
{
|
||||
"doc": "docs/core-data-structures/goal.md",
|
||||
"symbol": "CreateGoalRequest",
|
||||
"source": "packages/goal/goal/src/domain.ts"
|
||||
"source": "packages/goal/goal/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/goal.md",
|
||||
"symbol": "EditGoalRequest",
|
||||
"source": "packages/goal/goal/src/domain.ts"
|
||||
"source": "packages/goal/goal/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/goal.md",
|
||||
@@ -1494,6 +1494,66 @@
|
||||
"doc": "docs/core-data-structures/settings.md",
|
||||
"symbol": "SettingsPathOp",
|
||||
"source": "packages/settings/settings/src/index.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/typert.md",
|
||||
"symbol": "TypeRTLookupMap",
|
||||
"source": "packages/typert/type-meta/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/typert.md",
|
||||
"symbol": "TypeRTContextMap",
|
||||
"source": "packages/typert/type-meta/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/typert.md",
|
||||
"symbol": "TypeRTLookupDefinition",
|
||||
"source": "packages/typert/type-meta/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/typert.md",
|
||||
"symbol": "TypeRTCodec",
|
||||
"source": "packages/typert/type-meta/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/typert.md",
|
||||
"symbol": "InvocationParameterDescriptor",
|
||||
"source": "packages/typert/type-meta/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/typert.md",
|
||||
"symbol": "InvocationDescriptor",
|
||||
"source": "packages/typert/type-meta/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/typert.md",
|
||||
"symbol": "TypeRTService",
|
||||
"source": "packages/typert/type-meta/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/typert.md",
|
||||
"symbol": "TypeRTRemoteNamespaceMap",
|
||||
"source": "packages/typert/type-meta/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/typert.md",
|
||||
"symbol": "InvokeRemoteRequest",
|
||||
"source": "packages/api/gateway/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/typert.md",
|
||||
"symbol": "TypertGatewayErrorCode",
|
||||
"source": "packages/api/gateway/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/typert.md",
|
||||
"symbol": "TypertGateway",
|
||||
"source": "packages/api/gateway/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/typert.md",
|
||||
"symbol": "TypeRTClientRemote",
|
||||
"source": "packages/typert/type-meta/src/types.ts"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -58,10 +58,12 @@ const SENTENCE_MODEL_EXPERIENCE: Readonly<Record<string, SentenceContract>> = {
|
||||
'packages/client/web-react': { kind: 'none', reason: 'Browser-side UI plugin layer; registers no model surface.' },
|
||||
'packages/client/schema-form': { kind: 'none', reason: 'Browser-side form-rendering library; registers no model surface.' },
|
||||
'packages/client/connection': { kind: 'none', reason: 'Browser-side UI plugin layer; registers no model surface.' },
|
||||
'packages/api/remotes': { kind: 'none', reason: 'The Remote BFF selects business methods and identity policy; selected services own any model-visible effect.' },
|
||||
'packages/client/runtime': { kind: 'none', reason: 'Browser-side UI plugin layer; registers no model surface.' },
|
||||
'packages/client/ui-layout': { kind: 'none', reason: 'Browser-side UI plugin layer; registers no model surface.' },
|
||||
'packages/client/ui-sidebar': { kind: 'none', reason: 'Browser-side UI plugin layer; registers no model surface.' },
|
||||
'packages/client/ui-conversation': { kind: 'none', reason: 'Browser-side UI plugin layer; registers no model surface.' },
|
||||
'packages/client/ui-deliverables': { kind: 'none', reason: 'Browser-side UI plugin layer; registers no model surface.' },
|
||||
'packages/client/ui-slash': { kind: 'none', reason: 'Browser-side UI plugin layer; registers no model surface.' },
|
||||
'packages/client/ui-command': { kind: 'indirect', reason: 'The dispatch paths trigger the host command.execute RPC; each command handler\'s host package owns any model-visible effect.' },
|
||||
'packages/client/ui-model': { kind: 'indirect', reason: 'Selection routes session.selectModel; the host snapshots the target at the next prompt-assembly boundary and owns the model-visible effect.' },
|
||||
@@ -125,6 +127,8 @@ const SENTENCE_MODEL_EXPERIENCE: Readonly<Record<string, SentenceContract>> = {
|
||||
'packages/support/loader-smoke': { kind: 'none', reason: 'The test harness observes child-process streams without changing live requests.' },
|
||||
'packages/support/llm-mock-server': { kind: 'none', reason: 'The test server substitutes provider wire behavior without invoking a real model.' },
|
||||
'packages/support/llm-replay': { kind: 'none', reason: 'The keyless adapter invokes no provider model.' },
|
||||
'packages/api/gateway': { kind: 'none', reason: 'Remote dispatch infrastructure; invoked business methods own any model-visible effect.' },
|
||||
'packages/typert/type-meta': { kind: 'none', reason: 'Compiler-independent Remote protocol declarations; registers no model surface.' },
|
||||
'packages/typert/generator': { kind: 'none', reason: 'The build-time generator runs outside any agent runtime and touches no model request.' },
|
||||
'packages/tasks/tasks': { kind: 'indirect', reason: 'Producer and control-surface plugins own all model rendering over the task registry.' },
|
||||
'packages/tasks/tasks-local': { kind: 'indirect', reason: 'The registry backend delegates model rendering to producer plugins and dsh-tool-tasks.' },
|
||||
|
||||
@@ -204,11 +204,14 @@ cat "$scratch/logs/smoke.log"
|
||||
grep -q '^smoke: win32 x64' "$scratch/logs/smoke.log" || { echo 'wine-windows-gates: Windows Node smoke did not report win32 x64' >&2; exit 1; }
|
||||
|
||||
# ---- the two blocking surfaces, concurrently ------------------------------
|
||||
# The same shape run-gates gives ci-windows-blocking on native Windows:
|
||||
# `build` = tsc -b then tsdown, `production site` = the VitePress build. Both
|
||||
# statuses are captured so one failure cannot hide the other's result.
|
||||
# The build preserves the face order from package.json: generate Host contracts
|
||||
# before either aggregate typecheck, then bundle the completed workspace.
|
||||
# Both statuses are captured so one failure cannot hide the other's result.
|
||||
build_gate() {
|
||||
wine_node "$scratch/logs/tsc.log" "$tsc_js" -b --pretty false || return $?
|
||||
wine_node "$scratch/logs/contracts-tsc.log" "$tsc_js" -b packages/typert/generator --pretty false || return $?
|
||||
wine_node "$scratch/logs/contracts-tsdown.log" "$tsdown_js" --config tsdown.typert-host.config.ts || return $?
|
||||
wine_node "$scratch/logs/host-tsc.log" "$tsc_js" -b tsconfig.host.json --pretty false || return $?
|
||||
wine_node "$scratch/logs/client-tsc.log" "$tsc_js" -b tsconfig.client.json --pretty false || return $?
|
||||
wine_node "$scratch/logs/tsdown.log" "$tsdown_js"
|
||||
}
|
||||
site_gate() {
|
||||
@@ -235,7 +238,12 @@ report() {
|
||||
for log in "$@"; do tail -n 200 "$log" >&2 || true; done
|
||||
fi
|
||||
}
|
||||
report 'build (tsc -b, tsdown)' "$build_status" "$scratch/logs/tsc.log" "$scratch/logs/tsdown.log"
|
||||
report 'build (contract prepass, tsc, tsdown)' "$build_status" \
|
||||
"$scratch/logs/contracts-tsc.log" \
|
||||
"$scratch/logs/contracts-tsdown.log" \
|
||||
"$scratch/logs/host-tsc.log" \
|
||||
"$scratch/logs/client-tsc.log" \
|
||||
"$scratch/logs/tsdown.log"
|
||||
report 'production site (vitepress build)' "$site_status" "$scratch/logs/site.log"
|
||||
if (( build_status != 0 )); then exit "$build_status"; fi
|
||||
exit "$site_status"
|
||||
|
||||
Reference in New Issue
Block a user