Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .fallowrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@
},
{
"comment": "Type-level `AssertTrue<...>` registry-totality guards. Exported only so `noUnusedLocals` keeps them alive; a consumer would defeat the point.",
"file": "{src/core/command-descriptor/registry.ts,src/core/interactors/register-builtins.ts,src/core/platform-descriptor/registry.ts,src/daemon/request-platform-providers.ts}",
"file": "{packages/command-registry/src/registry.ts,src/core/interactors/register-builtins.ts,src/core/platform-descriptor/registry.ts,src/daemon/request-platform-providers.ts}",
"exports": [
"CommandOwnerFileClaimsAreComplete",
"BuiltinPluginsCoverAllPlatforms",
Expand Down
6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ normal app-driving startup follows the skill's routing card.
Read the declaration rather than maintaining a prose copy:

- commands and their surface, runtime-use, batch, and timeout traits:
`src/core/command-descriptor/registry.ts`
`packages/command-registry/src/registry.ts`
- daemon route ownership and request-policy traits: `src/daemon/daemon-command-registry.ts`
- interaction paths and guarantees: `packages/contracts/src/interaction-guarantees.ts`
- canonical command names: `src/command-catalog.ts`
- canonical command names: `packages/command-registry/src/catalog.ts`
- device runtime-use declarations and fact admission:
`src/core/command-descriptor/registry.ts`, `src/daemon/runtime-admission.ts`, and
`packages/command-registry/src/registry.ts`, `src/daemon/runtime-admission.ts`, and
`src/platform-runtime-gateway.ts`
- common command input fields, and which surface may write an input key (model, operator, retired):
`src/commands/common-input-fields.ts` and `src/commands/input-audience.ts`
Expand Down
2 changes: 1 addition & 1 deletion examples/sdk/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@
// prior build, workspace link, or publish step. Running an example for real
// still resolves `agent-device` as a self-referencing package (needs
// `pnpm build`), matching how a real consumer would import it.
"include": [".", "../../src/global.d.ts"]
"include": [".", "../../packages/command-registry/src/global.d.ts"]
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@
"check:unit": "pnpm test:unit && pnpm check:tmpdir-leaks && pnpm test:smoke",
"check": "pnpm check:tooling && pnpm check:fallow && pnpm check:unit",
"prepack": "pnpm check:mcp-metadata && pnpm package:npm",
"typecheck": "tsc -b packages/xml packages/kernel packages/contracts packages/host-kit packages/capture-kit packages/managed-allocation packages/provision-kit packages/platform-apple packages/platform-android packages/platform-harmonyos packages/platform-vega packages/platform-linux packages/platform-web packages/ad-script packages/selectors packages/ad-replay packages/maestro packages/replay-test packages/provider-webdriver packages/provider-limrun && tsc -p tsconfig.json && tsc -p examples/sdk/tsconfig.json",
"typecheck": "tsc -b packages/xml packages/kernel packages/contracts packages/host-kit packages/capture-kit packages/managed-allocation packages/provision-kit packages/platform-apple packages/platform-android packages/platform-harmonyos packages/platform-vega packages/platform-linux packages/platform-web packages/ad-script packages/selectors packages/command-registry packages/ad-replay packages/maestro packages/replay-test packages/provider-webdriver packages/provider-limrun && tsc -p tsconfig.json && tsc -p examples/sdk/tsconfig.json",
"test-app:install": "pnpm install --dir examples/test-app",
"test-app:start": "pnpm --dir examples/test-app start",
"test-app:ios": "pnpm --dir examples/test-app ios",
Expand Down Expand Up @@ -277,6 +277,7 @@
"@agent-device/ad-replay": "workspace:*",
"@agent-device/ad-script": "workspace:*",
"@agent-device/capture-kit": "workspace:*",
"@agent-device/command-registry": "workspace:*",
"@agent-device/contracts": "workspace:*",
"@agent-device/host-kit": "workspace:*",
"@agent-device/kernel": "workspace:*",
Expand Down
62 changes: 62 additions & 0 deletions packages/command-registry/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"name": "@agent-device/command-registry",
"version": "0.0.0",
"private": true,
"sideEffects": false,
"type": "module",
"description": "The command descriptor registry: the single declaration of every command's surface, runtime-use, batch, timeout, and platform-execution traits, plus the catalogs and projections derived from it.",
"dependencies": {
"@agent-device/contracts": "workspace:*",
"@agent-device/selectors": "workspace:*"
},
"exports": {
"./registry": {
"types": "./src/registry.ts",
"default": "./src/registry.ts"
},
"./catalog": {
"types": "./src/catalog.ts",
"default": "./src/catalog.ts"
},
"./types": {
"types": "./src/types.ts",
"default": "./src/types.ts"
},
"./timeout-policy": {
"types": "./src/timeout-policy.ts",
"default": "./src/timeout-policy.ts"
},
"./command-result": {
"types": "./src/command-result.ts",
"default": "./src/command-result.ts"
},
"./daemon-command-descriptor": {
"types": "./src/daemon-command-descriptor.ts",
"default": "./src/daemon-command-descriptor.ts"
},
"./derive": {
"types": "./src/derive.ts",
"default": "./src/derive.ts"
},
"./owner-files": {
"types": "./src/owner-files.ts",
"default": "./src/owner-files.ts"
},
"./platform-execution-entry": {
"types": "./src/platform-execution-entry.ts",
"default": "./src/platform-execution-entry.ts"
},
"./post-action-observation": {
"types": "./src/post-action-observation.ts",
"default": "./src/post-action-observation.ts"
},
"./parse-timeout": {
"types": "./src/parse-timeout.ts",
"default": "./src/parse-timeout.ts"
},
"./wait-positionals": {
"types": "./src/wait-positionals.ts",
"default": "./src/wait-positionals.ts"
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { test } from 'vitest';
import assert from 'node:assert/strict';
import { PUBLIC_COMMANDS } from '../../../command-catalog.ts';
import { PUBLIC_COMMANDS } from '../catalog.ts';
import { commandDescriptors, resolveCommandDeviceClaimPolicy } from '../registry.ts';
import type { DeviceClaimPolicy } from '../types.ts';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import {
type DescriptorCatalogRecord,
type DescriptorCliCommandName,
type DescriptorCommandNameForCatalogGroup,
} from './core/command-descriptor/registry.ts';
import type { CommandCatalogGroup } from './core/command-descriptor/types.ts';
} from './registry.ts';
import type { CommandCatalogGroup } from './types.ts';

export const PUBLIC_COMMANDS = deriveCommandCatalog('public');
export const INTERNAL_COMMANDS = deriveCommandCatalog('internal');
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import type { DispatchedCommand } from '@agent-device/contracts/command';
import type { RefFrameEffect } from '@agent-device/contracts/replay';
import { isReadOnlyFindAction, parseFindArgs } from '@agent-device/selectors';
import { resolveWaitBudgetMs } from '../wait-positionals.ts';
import { resolveWaitBudgetMs } from './wait-positionals.ts';
import {
DEFAULT_TIMEOUT_POLICY,
INSTALL_REQUEST_TIMEOUT_MS,
Expand Down
12 changes: 12 additions & 0 deletions packages/command-registry/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"composite": true,
"noEmit": false,
"emitDeclarationOnly": true,
"declaration": true,
"declarationDir": "./dist-types",
"rootDir": "./src"
},
"include": ["src"]
}
12 changes: 12 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions scripts/__tests__/eager-closure-budgets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,6 @@ export function discoverFacadeEntryFiles(repoRoot: string): string[] {
export const HUB_ENTRY_FILES: readonly string[] = [
'src/cli.ts',
'src/platform-runtime.ts',
'src/core/command-descriptor/registry.ts',
'src/core/command-descriptor/platform-execution-entry.ts',
'src/core/interactors/register-builtins.ts',
'src/daemon/session-teardown.ts',
];
Expand Down
2 changes: 1 addition & 1 deletion scripts/check-bundle-owner-files.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import fs from 'node:fs';
import path from 'node:path';
import { COMMAND_OWNER_FILES } from '../src/core/command-descriptor/owner-files.ts';
import { COMMAND_OWNER_FILES } from '@agent-device/command-registry/owner-files';
import { getDaemonRouteOwnerFiles } from '../src/daemon/route-owner-files.ts';
import { walkFiles } from './lib/walk-files.ts';

Expand Down
2 changes: 1 addition & 1 deletion scripts/depgraph/affected-run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import fs from 'node:fs';
import path from 'node:path';
import { pathToFileURL } from 'node:url';
import { PUBLIC_COMMANDS } from '../../src/command-catalog.ts';
import { PUBLIC_COMMANDS } from '@agent-device/command-registry/catalog';
import {
INTERACTION_DISPATCH_PATHS,
type InteractionPathId,
Expand Down
2 changes: 1 addition & 1 deletion scripts/fuzz/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export async function generateAndCheck(
* The split is organizational only. It was first committed claiming it kept the CLI schema
* registry out of corpus-replay's instrumented module graph; that claim was wrong.
* `corpus-replay.test.ts` imports `targets.ts`, which imports `src/cli/parser/args.ts`, which
* already pulls `command-schema`, `option-schema`, and `command-catalog`, and coverage instruments
* already pulls `command-schema`, `option-schema`, and the command catalog, and coverage instruments
* `src/**` only — the instrumented set is identical either way. What actually fixed the
* coverage-instrumented startup was deriving the CLI surface lazily in `validation-arbitraries.ts`;
* `validationSurfaceBuildCount()` is the guard against that regressing.
Expand Down
2 changes: 1 addition & 1 deletion scripts/fuzz/validation-arbitraries-cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import fc from 'fast-check';
import { describe, expect, it, vi } from 'vitest';
import { listCliCommandNames } from '../../src/command-catalog.ts';
import { listCliCommandNames } from '@agent-device/command-registry/catalog';
import { getFlagDefinitions } from '../../src/cli-schema/command-schema.ts';
import { getFuzzTarget } from './registry.ts';
import { decodeValidationCase } from './validation-case.ts';
Expand Down
2 changes: 1 addition & 1 deletion scripts/fuzz/validation-arbitraries-cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// parser against it, which is what makes a silent acceptance (the #1433 class) reportable at all.

import fc from 'fast-check';
import { isKnownCliCommandName, listCliCommandNames } from '../../src/command-catalog.ts';
import { isKnownCliCommandName, listCliCommandNames } from '@agent-device/command-registry/catalog';
import {
getCliCommandSchema,
getFlagDefinitions,
Expand Down
2 changes: 1 addition & 1 deletion scripts/integration-progress-model.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import fs from 'node:fs';
import path from 'node:path';
import { PUBLIC_COMMANDS } from '../src/command-catalog.ts';
import { PUBLIC_COMMANDS } from '@agent-device/command-registry/catalog';
import { listCommandMetadata } from '../src/commands/command-metadata.ts';
import { getFlagDefinitions } from '../src/commands/cli-grammar/flag-registry.ts';
import { walkFiles } from './lib/walk-files.ts';
Expand Down
2 changes: 1 addition & 1 deletion scripts/layering/model.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ test('every production zone is deliberately classified as ranked or unranked', (

test('listSourceFiles includes root-level src/*.ts production files', () => {
const files = new Set(listSourceFiles());
for (const rootFile of ['src/cli.ts', 'src/command-catalog.ts', 'src/backend.ts']) {
for (const rootFile of ['src/cli.ts', 'src/runtime.ts', 'src/backend.ts']) {
assert.ok(files.has(rootFile), `expected ${rootFile} in analyzed source files`);
}
assert.ok(![...files].some((file) => file.endsWith('.test.ts')));
Expand Down
1 change: 1 addition & 0 deletions scripts/layering/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export type BackEdgeMap = Record<string, string[]>;
const TARGET_DAG_RANK = new Map([
['ad-replay', 1],
['ad-script', 1],
['command-registry', 1],
['contracts', 1],
['maestro', 1],
['recording', 1],
Expand Down
6 changes: 3 additions & 3 deletions scripts/layering/record-runtime-registry-policy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ test('R16 requires the real registry normalization path to assert the record use
assert.deepEqual(
recordRuntimeRegistryJoinViolations([
{
path: 'src/core/command-descriptor/registry.ts',
path: 'packages/command-registry/src/registry.ts',
source: `
import { assertRecordRuntimeExecution as assertRecord } from '@agent-device/contracts/platform';
if (descriptor.name === 'record') assertRecord(platformExecution);
Expand All @@ -18,14 +18,14 @@ test('R16 requires the real registry normalization path to assert the record use
assert.deepEqual(
recordRuntimeRegistryJoinViolations([
{
path: 'src/core/command-descriptor/registry.ts',
path: 'packages/command-registry/src/registry.ts',
source: `
// assertRecordRuntimeExecution(platformExecution) is only prose.
const prose = 'record descriptor assertion';
normalize(platformExecution);
`,
},
]),
['src/core/command-descriptor/registry.ts: missing record runtime descriptor join assertion'],
['packages/command-registry/src/registry.ts: missing record runtime descriptor join assertion'],
);
});
6 changes: 3 additions & 3 deletions scripts/layering/record-runtime-registry-policy.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Catches: src/core/command-descriptor/registry.ts's record command descriptor missing the
// Catches: packages/command-registry/src/registry.ts's record command descriptor missing the
// runtime-descriptor join assertion — a wiring gap where record's registry entry silently
// stops being checked against the request-bound runtime it must join, invisible to a type
// check because the assertion's absence is not a type error, just a missing call.
Expand All @@ -16,7 +16,7 @@ import { memberName, type ProductionSource, visitAst } from './layering-ast.ts';
export function recordRuntimeRegistryJoinViolations(
sources: readonly ProductionSource[],
): string[] {
const file = sources.find(({ path }) => path === 'src/core/command-descriptor/registry.ts');
const file = sources.find(({ path }) => path === 'packages/command-registry/src/registry.ts');
if (!file) return [missingRecordRuntimeRegistryJoin()];
const parsed = parseSync(file.path, file.source);
const assertionName = importedRecordRuntimeAssertionName(parsed.program);
Expand All @@ -35,7 +35,7 @@ export function recordRuntimeRegistryJoinViolations(
}

function missingRecordRuntimeRegistryJoin(): string {
return 'src/core/command-descriptor/registry.ts: missing record runtime descriptor join assertion';
return 'packages/command-registry/src/registry.ts: missing record runtime descriptor join assertion';
}

function importedRecordRuntimeAssertionName(node: unknown): string | undefined {
Expand Down
2 changes: 1 addition & 1 deletion scripts/layering/runtime-execution-policy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import assert from 'node:assert/strict';
import { test } from 'node:test';
import { runtimeExecutionIntegrityViolations } from './runtime-execution-policy.ts';

const REGISTRY = 'src/core/command-descriptor/registry.ts';
const REGISTRY = 'packages/command-registry/src/registry.ts';
const ADMISSION = 'src/daemon/runtime-admission.ts';

function sources(entries: readonly (readonly [string, string])[]): ReadonlyMap<string, string> {
Expand Down
2 changes: 1 addition & 1 deletion scripts/layering/runtime-execution-policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type AstNode = Record<string, unknown>;

export const RUNTIME_EXECUTION_INTEGRITY_RULE = 'R66 runtime-execution-integrity';

const COMMAND_DESCRIPTOR_MODULE = 'src/core/command-descriptor/registry.ts';
const COMMAND_DESCRIPTOR_MODULE = 'packages/command-registry/src/registry.ts';
const RUNTIME_ADMISSION_MODULE = 'src/daemon/runtime-admission.ts';
const RUNTIME_PROOF_TYPES = new Set(['AdmittedRuntimePlan', 'BoundDeviceRuntime']);

Expand Down
2 changes: 1 addition & 1 deletion scripts/layering/tracked-sources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import { execFileSync } from 'node:child_process';

// `src/**/*.ts` only matches NESTED files, so root-level `src/*.ts` (src/cli.ts,
// src/command-catalog.ts) needs its own pathspec or it silently drops out of every scan.
// src/backend.ts) needs its own pathspec or it silently drops out of every scan.
// Workspace package sources are production files too (#1490 W0).
const TRACKED_SOURCE_PATHSPECS = [
'src/*.ts',
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
type WaitCommandResult,
} from '../agent-device-client.ts';
import { runCommand } from '../commands/command-surface.ts';
import type { CommandResult } from '../core/command-descriptor/command-result.ts';
import type { CommandResult } from '@agent-device/command-registry/command-result';
import type { DaemonResponse, DaemonResponseData } from '@agent-device/kernel/contracts';
import { AppError } from '@agent-device/kernel/errors';
import fs from 'node:fs';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import assert from 'node:assert/strict';
import { test } from 'vitest';
import { STRUCTURED_BATCH_COMMAND_NAMES } from '../../batch-policy.ts';
import { STRUCTURED_BATCH_COMMAND_NAMES } from '../core/batch-policy.ts';
import {
INTERNAL_COMMANDS,
listCliCommandNames,
PUBLIC_COMMANDS,
} from '../../../command-catalog.ts';
} from '@agent-device/command-registry/catalog';
import {
DAEMON_COMMAND_DESCRIPTORS,
canRunReplayScopedAction,
type DaemonCommandDescriptor,
} from '../../../daemon/daemon-command-registry.ts';
import type { DaemonRequest } from '../../../daemon/types.ts';
import { deriveDaemonCommandDescriptors, deriveStructuredBatchCommandNames } from '../derive.ts';
} from '../daemon/daemon-command-registry.ts';
import type { DaemonRequest } from '../daemon/types.ts';
import {
deriveDaemonCommandDescriptors,
deriveStructuredBatchCommandNames,
} from '@agent-device/command-registry/derive';
import {
commandDescriptors,
listDescriptorCatalogCommandNames,
Expand All @@ -22,7 +25,7 @@ import {
resolveCommandRecordingEffect,
resolveTargetIdentityVerification,
RAW_COMMAND_DESCRIPTORS,
} from '../registry.ts';
} from '@agent-device/command-registry/registry';

// Function-valued traits cannot be deep-equaled across re-authored closures, so
// (mirroring daemon-command-registry.test.ts) they are compared by presence and
Expand Down
Loading
Loading