Merge remote-tracking branch 'origin/master' into feat/loader-entry-disabled-interpolation
# Conflicts: # scripts/verify-cordis-config.ts
This commit is contained in:
@@ -83,6 +83,7 @@ if (import.meta.main) {
|
||||
errors.push(...validateAppResolution())
|
||||
errors.push(...validateSourcePlaneResolution())
|
||||
errors.push(...validatePresetPlaneSeparation())
|
||||
errors.push(...validateClientHalvesDeclared())
|
||||
|
||||
if (errors.length > 0) {
|
||||
console.error('verify-cordis-config: invalid Loader metadata or plugin package resolution:')
|
||||
@@ -93,6 +94,35 @@ if (import.meta.main) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A browser plugin must declare the browser half it ships.
|
||||
*
|
||||
* The browser roster is discovered by scanning composed packages for a
|
||||
* `dsh.client` block, and the node half of a surface plugin is an empty
|
||||
* `apply`. A `packages/client` package that exports `./client` without that
|
||||
* block therefore composes, activates, and contributes nothing — its bundle is
|
||||
* never served and no error is raised anywhere. The mismatch is invisible in
|
||||
* the composition file, so it is checked against the manifests instead. Only
|
||||
* this group is checked: a Host package's `./client` export is the typed wire
|
||||
* face its browser consumers import, not a plugin the roster serves.
|
||||
* @returns one violation per client package whose `./client` export and
|
||||
* `dsh.client` declaration disagree.
|
||||
*/
|
||||
function validateClientHalvesDeclared(): string[] {
|
||||
return globSync('packages/client/*/package.json', { cwd: root }).flatMap((manifestPath) => {
|
||||
const manifest = readManifest(manifestPath) as PackageManifest & {
|
||||
exports?: Record<string, unknown>
|
||||
dsh?: { client?: unknown }
|
||||
}
|
||||
const shipsClient = manifest.exports !== undefined && Object.hasOwn(manifest.exports, './client')
|
||||
const declaresClient = manifest.dsh?.client !== undefined
|
||||
if (shipsClient === declaresClient) return []
|
||||
return [shipsClient
|
||||
? `${manifestPath}: exports "./client" but declares no dsh.client, so its browser half is never served`
|
||||
: `${manifestPath}: declares dsh.client but exports no "./client" entry to serve`]
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* No shipped agent preset may repeat a row the host composition still runs.
|
||||
*
|
||||
|
||||
@@ -84,7 +84,9 @@ const mermaid = (await import('mermaid')).default
|
||||
// maxEdges: mermaid's default 500-edge render guard; the module graph grows
|
||||
// with every package edge and crossed it legitimately. Raise the guard here
|
||||
// (a secure config settable only via initialize) rather than trimming edges.
|
||||
mermaid.initialize({ startOnLoad: false, maxEdges: 1000 })
|
||||
// The graph passed 1000 the same way it passed 500, so the headroom doubles
|
||||
// again rather than being set to whatever the current count happens to be.
|
||||
mermaid.initialize({ startOnLoad: false, maxEdges: 2000 })
|
||||
for (const block of blocks) {
|
||||
try {
|
||||
await mermaid.parse(block.source, { suppressErrors: false })
|
||||
|
||||
@@ -80,6 +80,7 @@ const SENTENCE_MODEL_EXPERIENCE: Readonly<Record<string, SentenceContract>> = {
|
||||
'packages/client/ui-model': { kind: 'indirect', reason: 'Selection routes session.selectModel; the Host snapshots the selection at the next prompt-assembly boundary and owns the model-visible effect.' },
|
||||
'packages/client/ui-goal': { kind: 'indirect', reason: 'The strip verbs route goal.* mutations; the host GoalService owns the model-visible goal/change context message.' },
|
||||
'packages/client/ui-permission': { kind: 'indirect', reason: 'The picker submits the host /permission command; the knob events it appends own the model-visible effect through the sandbox/approval consumers.' },
|
||||
'packages/client/ui-plugin-config': { kind: 'none', reason: 'Browser-side settings surface; registers no model surface.' },
|
||||
'packages/client/ui-plan': { kind: 'indirect', reason: 'The chip dispatches /plan off; dsh-plan-mode owns the model-visible policy, exit tool, and logged state.' },
|
||||
'packages/client/ui-question': { kind: 'indirect', reason: 'The package mounts dsh-tool-ask-user; that tool owns the model-visible schema and answer rendering.' },
|
||||
'packages/client/ui-trajectory': { kind: 'none', reason: 'Browser-side UI plugin layer; registers nothing model-facing.' },
|
||||
|
||||
Reference in New Issue
Block a user